diff --git a/PMM-sample.md b/PMM-sample.md
new file mode 100644
index 0000000..ad1eb45
--- /dev/null
+++ b/PMM-sample.md
@@ -0,0 +1,288 @@
+
+
+
+

+
PMM example
+
+
+## Overview
+
+This is special example which shows how to use PMM liquidity without using SDK, only using few libraries
+
+```ts
+import {ethers, Wallet} from "ethers";
+import {z} from "zod";
+import hmacSHA256 from "crypto-js/hmac-sha256";
+import Hex from "crypto-js/enc-hex";
+
+///////////////////////////////
+///////////////////////////////
+const pmmOrderQuotationSchema = z.object({
+ info: z.string().default(''),
+ makerAsset: z.string().default(''),
+ takerAsset: z.string().default(''),
+ maker: z.string().default(''),
+ allowedSender: z.string().default(''),
+ makingAmount: z.string().default(''),
+ takingAmount: z.string().default(''),
+});
+
+const pmmOrderSchema = z.object({
+ order: pmmOrderQuotationSchema.default({}),
+ signature: z.string().default(''),
+ success: z.boolean().default(false),
+ error: z.string().default(''),
+});
+
+const orionRFQContractABI =
+ [
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "info",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "makerAsset",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "takerAsset",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "maker",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "allowedSender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "makingAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "takingAmount",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct OrderRFQLib.OrderRFQ",
+ "name": "order",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "flagsAndAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "fillOrderRFQ",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ];
+
+function encode_utf8(s : string) {
+ return unescape(encodeURIComponent(s));
+}
+function sign(message : string, key: string) {
+ return hmacSHA256(
+ encode_utf8(message),
+ encode_utf8(key)
+ ).toString(Hex);
+}
+
+function generateHeaders(body : any, method : string, path : string, timestamp : number, apiKey : string, secretKey : string) {
+ const sortedBody = Object.keys(body)
+ .sort()
+ .map((key) => (
+ `${key}=${body[key]}`
+ )).join('&');
+
+ const payload = timestamp + method.toUpperCase() + path + sortedBody;
+
+ const signature = sign(payload, secretKey);
+
+ const httpOptions = {
+ headers: {
+ 'API-KEY': apiKey,
+ 'ACCESS-TIMESTAMP': timestamp.toString(),
+ 'ACCESS-SIGN': signature
+ }
+ };
+ return httpOptions;
+}
+
+//
+async function RFQOrder(
+ tokenFrom: string,
+ tokenTo: string,
+ fromTokenAmount: string,
+ apiKey: string, //
+ secretKey: string,
+ wallet: string
+) : Promise> {
+
+ // NB: replace with correct URL for networks
+ const apiUrl = 'https://testing.orion.xyz/bsc-testnet/backend'
+ // const apiUrl = 'https://trade.orion.xyz/bsc-mainnet/backend'
+ , path = '/rfq'
+ , url = `${apiUrl}/api/v1/integration/pmm`+path
+ , headers = {
+ 'Content-Type': 'application/json',
+ }
+ , data = {
+ "baseToken":tokenFrom, // USDT
+ "quoteToken":tokenTo, // ORN
+ "amount": fromTokenAmount, // 100
+ "taker": wallet,
+ "feeBps": 0
+ }
+ , method = 'POST'
+ , timestamp = Date.now()
+ , signatureHeaders = generateHeaders(data, method, path, timestamp, apiKey, secretKey)
+ , compiledHeaders = {...headers, ...signatureHeaders.headers, }
+ , body = JSON.stringify(data)
+ ;
+
+ let res = pmmOrderSchema.parse({});
+
+ try {
+ const result = await fetch(url,{
+ headers: compiledHeaders,
+ method,
+ body
+ });
+
+ // const data = await result.text();
+ // console.log(data);
+
+ const json = await result.json();
+ console.log(json);
+ const parseResult = pmmOrderSchema.safeParse(json);
+
+ if(!parseResult.success) {
+ // Try to parse error answer
+ const errorSchema = z.object({error: z.object({code: z.number(), reason: z.string()})});
+
+ const errorParseResult = errorSchema.safeParse(json);
+
+ if(!errorParseResult.success)
+ throw Error(`Unrecognized answer from aggregator: ${json}`);
+
+ throw Error(errorParseResult.data.error.reason);
+ }
+
+ res.order = parseResult.data.order;
+ res.signature = parseResult.data.signature;
+ res.error = '';
+ res.success = true;
+ }
+ catch(err) {
+ res.error = `${err}`;
+ }
+ return res;
+}
+
+
+(async() => {
+ const apiKey = '958153f1-b8b9-3ec4-84eb-2147429105d9';
+ const secretKey = 'secretKey';
+
+ // BNB testnet tokens and router
+ const assetORN = '0xf223eca06261145b3287a0fefd8cfad371c7eb34';
+ const assetUSDT = '0xcb2951e90d8dcf16e1fa84ac0c83f48906d6a744';
+ const router = '0x89357522C0ed6E557D39dC75290859246077bdfC';
+
+ // BNB mainnet tokens and router
+ // const assetORN = '0xe4ca1f75eca6214393fce1c1b316c237664eaa8e';
+ // const assetUSDT = '0x55d398326f99059ff775485246999027b3197955';
+ // const router = '0xcb2D40EabC4f4c92Ee993Eb3D67f7717bE476E76';
+
+ const rfqOrder = await RFQOrder(
+ assetORN, // Spending asset
+ assetUSDT, // Receiving asset
+ '1000000000', // Amount in "satoshi" of spending asset
+ apiKey,
+ secretKey,
+ '0x61Eed69c0d112C690fD6f44bB621357B89fBE67F' // Can be any address, ignored for now
+ );
+
+ if(!rfqOrder.success) {
+ console.log(rfqOrder.error);
+ return;
+ }
+
+ // ... here you can check order prices, etc.
+ console.log(rfqOrder);
+
+ // Calldata according to provided rfqOrder
+ const contractInterface = new ethers.Interface(orionRFQContractABI);
+ const calldata = contractInterface.encodeFunctionData("fillOrderRFQ", [rfqOrder.order, rfqOrder.signature, 0]);
+ console.log('Calldata = ', calldata);
+
+ // Call router with this data
+ // Replace with your private key
+ const yourWalletPrivateKey = '0xf1.......';
+
+ const tx = {
+ to: router,
+ data: calldata
+ }
+
+ const provider = new ethers.JsonRpcProvider("https://data-seed-prebsc-1-s1.binance.org:8545/");
+ const signer = new ethers.Wallet(yourWalletPrivateKey, provider);
+ console.log('Address = ', signer.address);
+ const transactionResponse = await signer.sendTransaction(tx);
+ console.log("Transaction hash:", transactionResponse.hash);
+ await transactionResponse.wait();
+})();
+```
+
+RFQ order response example description (`rfqOrder` from example above):
+
+```
+ {
+ quotation: {
+ info: '31545611720730315633520017429',
+ makerAsset: '0xcb2951e90d8dcf16e1fa84ac0c83f48906d6a744',
+ takerAsset: '0xf223eca06261145b3287a0fefd8cfad371c7eb34',
+ maker: '0x1ff516e5ce789085cff86d37fc27747df852a80a',
+ allowedSender: '0x0000000000000000000000000000000000000000',
+ makingAmount: '193596929',
+ takingAmount: '10000000000'
+ },
+ signature: '0x8a2f9140a3c3a5734eda763a19c54c5ac909d8a03db37d9804af9115641fd1d35896b66ca6e136c1c89e0478fb7382a4b875d0f74529c1e83601f9383d310dde1b',
+ success: true,
+ error: ''
+ }
+```
+
+
+* info - can be ignored
+* makerAsset - your RECEIVING asset (what you expect to receive from contract, in this case USDT)
+* takerAsset - your SPENDING asset (what you're giving to contract, in this case ORN)
+* maker - can be ignored for now;
+* allowedSender - can be ignored for now;
+* makingAmount - how much you will RECEIVE (in receiving asset's precision)
+* takingAmount - how much you should SPEND (in spending asset's precision)
\ No newline at end of file
diff --git a/package.json b/package.json
index cec14eb..a307337 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@orionprotocol/sdk",
- "version": "0.20.68-rc1",
+ "version": "0.20.79-rc1",
"description": "Orion Protocol SDK",
"main": "./lib/index.cjs",
"module": "./lib/index.js",
diff --git a/src/Unit/Pmm/index.ts b/src/Unit/Pmm/index.ts
index cb41136..d4f1c57 100644
--- a/src/Unit/Pmm/index.ts
+++ b/src/Unit/Pmm/index.ts
@@ -79,6 +79,6 @@ export default class Pmm {
const contract = new ethers.Contract(this.contractAddress, orionRFQContractABI, signer);
// @ts-ignore
- return contract.fillOrderRFQ(order.quotation, order.signature, BigInt(0));
+ return contract.fillOrderRFQ(order.order, order.signature, BigInt(0));
}
}
\ No newline at end of file
diff --git a/src/Unit/Pmm/schemas/order.ts b/src/Unit/Pmm/schemas/order.ts
index 2651660..a9727e4 100644
--- a/src/Unit/Pmm/schemas/order.ts
+++ b/src/Unit/Pmm/schemas/order.ts
@@ -11,7 +11,7 @@ export const pmmOrderQuotationSchema = z.object({
});
export const pmmOrderSchema = z.object({
- quotation: pmmOrderQuotationSchema.default({}),
+ order: pmmOrderQuotationSchema.default({}),
signature: z.string().default(''),
success: z.boolean().default(false),
error: z.string().default(''),
diff --git a/src/services/Aggregator/index.ts b/src/services/Aggregator/index.ts
index f04e4c5..1077a53 100644
--- a/src/services/Aggregator/index.ts
+++ b/src/services/Aggregator/index.ts
@@ -461,11 +461,10 @@ class Aggregator {
throw Error(errorParseResult.data.error.reason);
}
- res.quotation = parseResult.data.quotation;
+ res.order = parseResult.data.order;
res.signature = parseResult.data.signature;
res.error = '';
res.success = true;
- // return result;
}
catch(err) {
res.error = `${err}`;