Change dapp gateway - decentralized-applications

How can I change the elrond dapp gateway? I want to use tatum.io in exchange of gateway.elrond.com but with the elrond dapp template https://github.com/ElrondNetwork/dapp-template I don't know how to do it!
<DappProvider
environment={environment}
customNetworkConfig={{
name: 'customConfig',
gatewayAddress:'https://api-eu1.tatum.io/v3/egld/node/id',
apiTimeout: 10000
}}
completedTransactionsDelay={200}
>
gateAddress is not a valid key, only apiAddress so it's not working.
Thank you!

This is the interface of the customNetworkConfig:
export interface CustomNetworkType {
id?: string;
chainId?: string;
name?: string;
egldLabel?: string;
egldDenomination?: string;
decimals?: string;
gasPerDataByte?: string;
walletConnectDeepLink?: string;
walletConnectBridgeAddresses?: string[];
walletAddress?: string;
apiAddress?: string;
explorerAddress?: string;
skipFetchFromServer?: boolean;
apiTimeout?: string;
}
As you see, there isn't a gatewayAddress variable.
Could you explain us what you want to do by changing the gateway?

Related

How to make subscription with arguments correctly in GraphQL?

In AWS AppSync I tried to test my GraphQL schema. I'm a little confused and need help. My subscription called watchMessages doesn't work when there is an argument. If I remove the argument from schema and test it, it works. But I only need to receive messages from a specific room. What am I missing?
input CreateMessageInput {
roomId: String!
messageText: String
messageAuthor: String
}
type CreateMessageOutput {
messageId: String!
messageCreatedDateTime: String!
messageText: String!
messageAuthor: String
}
type Mutation {
createMessage(input: CreateMessageInput): CreateMessageOutput
}
type Subscription {
watchMessages(roomId: String!): CreateMessageOutput
#aws_subscribe(mutations: ["createMessage"])
}
I make such subscription query:
subscription MySubscription {
watchMessages(roomId: "5d354323") {
messageId
messageCreatedDateTime
messageText
messageAuthor
}
}
I make such mutation query:
mutation MyMutation {
createMessage(input: {roomId: "5d354323", messageAuthor: "Bob", messageText: "Hello!"}) {
messageId
messageCreatedDateTime
messageText
messageAuthor
}
}
Finally, I found the solution. All subscription parameters must exist as a field in the returning type. This means that the type of parameter must also match the type of the field in the returning object. I added roomId field to the CreateMessageOutput type.
type CreateMessageOutput {
roomId: String!
messageId: String!
messageCreatedDateTime: String!
messageText: String!
messageAuthor: String
}

Passing variables to an external resolve reference

I'm using Apollo Federation for 2 months but I'm actually stuck. I've no idea how to pass a variable between my two graphql services.
I've got a website (website graphql service) which have orders (orders graphql service).
I have a query to find websites and for these websites I want some stats of orders for a date range. Here the typedef (website) :
type Query {
websites(orderFilter: OrderFilterInput): [Website!]
}
type Website #key(fields: "id") {
id: ID!
name: String!
url: String!
orderSummary(orderFilter: OrderSummaryFilterInput): OrderSummary
}
input OrderSummaryFilterInput {
beginDate: Date
endDate: Date
}
extend type OrderSummary #key(fields: "websiteId") {
websiteId: String! #external
}
The resolver :
orderSummary: (website, { orderSummaryFilter }) => {
console.log("orderSummaryFilter", orderSummaryFilter); // filters are OK
// HOW CAN I PASS orderFilterSummary to my order graphql service here ????
return { __typename: "OrderSummary", websiteId: website.id };
}
And Order graphql service
Typedef part :
type OrderSummary #key(fields: "websiteId") {
websiteId: String!
count: Int
amount: Int
}
Resolver part :
// order gql service
OrderSummary: {
__resolveReference(website, args, info) {
console.log("website id :", website.id); // I ve got my website ID
// HOW TO GET OrderSummaryFilter here ????
},
},
How can I access to order summary filter variable in order graphql resolver ? Thank you.
From what I am aware of, it is not possible to send variables from one service to another other then the ID. But there is a solution to this.
If you want to pass in variables, extend your Website type in your order service instead of extending order type in website service.
Order typedef:
extend type Website #key(fields: "id") {
id: ID! #external
orderSummary(orderFilter: OrderSummaryFilterInput): OrderSummary #requires(fields:"id")
}
Order resolver:
Website: {
orderSummary: async (website, { orderFilter }) => getOrderSummary(orderFilter) //get orderSummary with orderFilter
},
So I want to expound on the previous (and I believe correct) answer:
In Federation, you almost never should have to expose a field called somethingId (userId, websiteId, etc). That is often either a left-over from Schema Stitching, or you simply got your type origins backward. Instead of using somethingId, you should be able to just use the object. Often, moving the #extend to the other service will get rid of the somethingId field, and get rid of the type of problem you're currently facing:
Website Service:
type Query {
websites(orderFilter: OrderFilterInput): [Website!]
}
type Website #key(fields: "id") {
id: ID!
name: String!
url: String!
}
Order Service:
extend type Website #key(fields: "id") {
id: ID! #external
orderSummary(orderFilter: OrderSummaryFilterInput): OrderSummary
}
input OrderSummaryFilterInput {
beginDate: Date
endDate: Date
}
type OrderSummary {
website: Website!
count: Int
amount: Int
}
Resolvers:
const resolvers = {
Website: {
orderSummary(parent, args, context) {
const websiteId = parent.id;
// args is the data you wanted
}
},
};

How to get a full list of loopback4 models to evaluate custom decorator metadata at boot time?

I'm currently migrating a loopback3 application to loopback4. I've annotated the properties in my loopback4 models with a custom typescript decorator with some metadata.
How can I get a full list of models and evaluate their metadata at boot time?
I did some experiments with LifeCycleObserver, but did not find a way how to get notified when all models are ready nor get a list of them.
Here is an simplified example of the metadata i want to process. Please note: #propertyAcl is a custom decorator.
export class Model1 extends AuditMixin(SoftdeleteMixin(AbstractEntity)) {
// ...
#property()
#propertyAcl({
'role1': Permission.READ_WRITE,
'role2': Permission.READONLY,
})
myproperty?: string;
// ...
}
I need to configure the external library accesscontrol with the metadata at boot time. The idea is to create property based acls per model.
How can I get a full list of models and evaluate their metadata at boot time?
Overview
Using #loopback/metadata to create a Decorator and define / get the metadata via MetadataInspector.
Create a DecoratorFactory "A"
Create a Context "B"
Overide the mergeWithInherited function in "A", and in this function we store (define) the metadata of the property that you annotated at design time to "B"
Create a Decorator "C" via "A"
Annotate any properties you want with "C"
Get the metadata in "B" at runtime
Step 1 2 3 4
// 1
class A extends PropertyDecoratorFactory<object> {
constructor(key: string, spec: object, options?: DecoratorOptions | undefined) {
super(key, spec, options);
}
// 3
mergeWithInherited(inheritedMetadata: MetadataMap<object>, target: Object, propertyName?: string, descriptorOrIndex?: TypedPropertyDescriptor<any> | number): any {
// define metadata to "B"
MetadataInspector.DesignTimeReflector.defineMetadata(`${target.constructor.name}.${propertyName}`, this.spec, B);
}
}
// 2
export const B = new Context("B.context");
// 4
export function C(spec: object): PropertyDecorator {
return A.createDecorator<object>(
'C.decorator',
spec,
);
}
Step 5
class ModelFoo extends Model {
#property({
type: 'string'
})
p1?: string;
#C({ metadata: "this is ModelFoo" })
#property({
type: 'string'
})
p2?: string;
}
class ModelBar extends Model {
#property({
type: 'string'
})
p1?: string;
#C({ metadata: "this is ModelBar" })
#property({
type: 'string'
})
p2?: string;
}
Step 6
function Test() {
// get all metadata keys in "B"
let keys: string[] = MetadataInspector.DesignTimeReflector.getMetadataKeys(B);
// output >>>> [ 'ModelFoo.p2', 'ModelBar.p2' ]
console.log(keys);
// get metadata with 'ModelFoo.p2' in "B"
let metadata = MetadataInspector.DesignTimeReflector.getMetadata(keys[0], B);
// output >>>> { metadata: 'this is ModelFoo' }
console.log(metadata);
// do somthing...
}

AWS AppSync - Directive "aws_subscribe" may not be used on FIELD_DEFINITION

I'm trying to get to grips with AWS AppSync. I'm quite new to GraphQL. I've got the following GraphQL:
type Mutation {
deleteParcel(geoHash: String!, type_id: String!): Parcel
addParcel(input: ParcelInput!): Parcel
batchAddParcels(parcels: [ParcelInput]): [Parcel]
}
type Parcel {
geoHash: String!
type_id: String!
}
type ParcelConnection {
items: [Parcel]
}
input ParcelInput {
geoHash: String!
type_id: String!
}
input ParcelsInput {
parcels: [ParcelInput]
}
type Query {
getNearbyParcels(geoHash: String!): ParcelConnection
}
type Subscription {
onAddParcel(geoHash: String, type_id: String): Parcel
#aws_subscribe(mutations: ["addParcel"])
onBatchAddParcels(geoHash: String): Parcel
#aws_subscribe(mutations: ["batchAddParcels"])
onDeleteParcel(geoHash: String, type_id: String): Parcel
#aws_subscribe(mutations: ["deleteParcel"])
}
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
All seems to be setup fine on AWS console. I get the schema.json and then run command:
aws-appsync-codegen generate AWSGraphQL.graphql --schema schema.json --output AppsyncAPI.swift
and get the response:
../SnatchHQ/snatch_appsync/AppSync/AWSGraphQL.graphql: Directive "aws_subscribe" may not be used on FIELD_DEFINITION.
.../SnatchHQ/snatch_appsync/AppSync/AWSGraphQL.graphql: Directive "aws_subscribe" may not be used on FIELD_DEFINITION.
.../SnatchHQ/snatch_appsync/AppSync/AWSGraphQL.graphql: Directive "aws_subscribe" may not be used on FIELD_DEFINITION.
error: Validation of GraphQL query document failed
Can anyone help?
If the file AWSGraphQL.graphql is your API GraphQL schema, then that explains the problem. What you need to do is define a *.graphql file that defines your query, mutation, and subscription operations based on your GraphQL API. For example, the following query definitions would match your schema
mutation AddParcel($geoHash: String!, $type_id: String!) {
addParcel(input: {
geoHash: $geoHash
type_id: $typeId
}) {
...Parcel
}
}
query GetNearbyParcels($geoHash: String!) {
getNearbyParcels(
geoHash: $geoHash
) {
...ParcelConnection
}
}
subscription OnAddParcel {
onAddParcel {
...Parcel
}
}
fragment Parcel on Parcel {
geoHash
type_id
}
fragment ParcelConnection on Parcel Connection {
items {
...Parcel
}
}
Assuming you named it something like parcels.graphql, you can then call the following to generate a Swift implementation of the AddParcel mutation, the GetNearbyParcels query, and the OnAddParcel subscription
aws-appsync-codegen generate parcels.graphql \
--schema schema.json \
--output AppSyncParcelsAPI.swift

Swift Siesta Get and post

I am new to Siesta. How can I get the entire array and pass into my model? Besides, how can I post with params? In their documentation I couldn't find any of this.
I'm new to siesta as well. I was able to find documentation about requests here http://bustoutsolutions.github.io/siesta/guide/requests/
Basically you'll setup your resource and then call:
resource.request(.post, json: ["foo": [1,2,3]])
Your question is far too complex so I will try to explain you in a simple way.
Siesta provides a great way to map your models by using Custom Transformers. One simple way to do this is to implement the Decodable protocol provided by Swift 4+:
Lets say we want to decode this JSON response:
{
"id": 1,
"name": "Oswaldo",
"email": "omaestra#gmail.com"
}
Into our great User class which implements the Decodable protocol:
class User: Decodable {
var id: Int
var name: String
var email: String
private enum CodingKeys: String, CodingKey {
case id, name, email
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: .id
name = try container.decode(String.self, forKey: .name)
email = try container.decode(String.self, forKey: .email)
}
}
Awesome! Now we can decode the JSON response from our server into our awesome User class.
Next, inside our Siesta.Service class we can configure our custom transformers for specific resources:
class API: Siesta.Service {
init() {
super.init(baseURL: "https://api.example.com")
// Some initial configuration
}
let myAPI = API()
// –––––– Global configuration ––––––
let jsonDecoder = JSONDecoder()
// –––––– Mapping from specific paths to models ––––––
// These all use Swift 4’s JSONDecoder, but you can configure arbitrary transforms on arbitrary data types.
configureTransformer("rest/user/") {
// Input type inferred because the from: param takes Data.
// Output type inferred because jsonDecoder.decode() will return User
try jsonDecoder.decode(User.self, from: $0.content)
}
// MARK: - Resources
var userResource: Siesta.Resource { return resource("rest/user/") }
}
Finally, we can implement our resource inside our ViewController:
class UserViewController: UIViewController {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var emailLabel: UILabel!!
override func viewDidLoad() {
super.viewDidLoad()
myAPI.userResource
.addObserver(self)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
myAPI.userResource.loadIfNeeded()
}
}
extension UserViewController: ResourceObserver {
func resourceChanged(_ resource: Resource, event: ResourceEvent) {
let user: User? = resource.typedContent()
nameLabel.text = user?.name
emailLabel.text = user?.email
}
}
Note: Siesta is very flexible and customisable framework, you can find multiple ways to configure your services and resources. This is just one simple way to implement what you are asking for.
To make a POST request with params you can do something like this inside your Service class:
Implement an update method that makes the POST request.
func update(user: User, newName: String) -> Siesta.Request {
return usersResource
.child(user.id)
.child("update")
.request(.post, json: ["name": newName])
}
Then, in your ViewController you can call the method to submit the POST request and evaluate its response:
myAPI.update(user: user, newName: "NEW NAME")
.onSuccess({ (_) in
print("Successfully updated user's name.")
})
.onFailure({ (error) in
print("Error trying to update user's name.")
})