Solvers
Example of signing solver intent
Example of how to create response for quote for solvers using TypeScript
Here params
has same type as what you receive from relay in "quote" event
params: {
defuse_asset_identifier_in: string;
defuse_asset_identifier_out: string;
exact_amount_in: string | undefined;
exact_amount_out: string | undefined;
min_deadline_ms: number;
},
const generateNonce = async (): Promise<string> => {
const randomArray = randomBytes(32);
return randomArray.toString('base64');
if (await this.isNonceUsed(nonceString)) { //this step can be skipped but if nonce is already used quote wont be taken into account
return this.generateNonce();
} else {
return nonceString;
}
}
const isNonceUsed = async (nonce: string) => {
const account = getAccount(); //function that will return Account instance(from "near-api-js") of solver Near account
return await account.viewFunction({
contractId: defuseContract,
methodName: 'is_nonce_used',
args: {
account_id: account.accountId,
nonce,
},
});
}
import { BorshSchema, borshSerialize } from 'borsher';
const standardNumber = {
["nep413"]: 413,
};
const Nep413PayloadSchema = BorshSchema.Struct({
message: BorshSchema.String,
nonce: BorshSchema.Array(BorshSchema.u8, 32),
recipient: BorshSchema.String,
callback_url: BorshSchema.Option(BorshSchema.String),
});
const serializeIntent = (
intentMessage: any,
recipient: string,
nonce: string,
standard: string,
): Buffer => {
const payload = {
message: intentMessage,
nonce: base64ToUint8Array(nonce),
recipient,
};
const payloadSerialized = borshSerialize(Nep413PayloadSchema, payload);
const baseInt = 2 ** 31 + standardNumber[standard];
const baseIntSerialized = borshSerialize(BorshSchema.u32, baseInt);
const combinedData = Buffer.concat([baseIntSerialized, payloadSerialized]);
return crypto.createHash('sha256').update(combinedData).digest();
}
const base64ToUint8Array = (base64: string): Uint8Array => {
const binaryString = atob(base64);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes;
}
const signMessage = async (message: Uint8Array) { //you can implement your own way to sign message with near wallet
return (await keyStore.getKey(nearNetworkId, accountId)).sign(message); //keyStore is instance of KeyStore(from "near-api-js")
}
import bs58 from 'bs58';
const amount = "1000" //calculated amount solver want to propose
const standard = "nep413";
const message = {
signer_id: "...", //account id of solver account that will be used for signing
deadline: {
timestamp: 10000, //timestamp deadline in seconds
},
intents: [
{
intent: 'token_diff',
diff: {
[params.defuse_asset_identifier_in]: !!params.exact_amount_in
? params.exact_amount_in
: amount,
[params.defuse_asset_identifier_out]: `-${
!!params.exact_amount_out ? params.exact_amount_out : amount
}`,
},
},
],
};
const messageStr = JSON.stringify(message);
const nonce = await generateNonce();
const recipient = defuseContract; //for example "intents.near"
const quoteHash = serializeIntent(messageStr, recipient, nonce, standard);
const signature = signMessage(quoteHash);
const resp: IQuoteObject = {
quote_id,
quote_output: {},
signed_data: {
standard,
payload: {
message: messageStr,
nonce,
recipient,
},
signature: `ed25519:${bs58.encode(signature.signature)}`,
public_key: `ed25519:${bs58.encode(signature.publicKey.data)}`,
},
};
if (!params.exact_amount_in) {
resp.quote_output.amount_in = amount;
} else {
resp.quote_output.amount_out = amount;
}
Last updated