From 6788008dd51f8528a7ec7429379f1b6b94f26ba4 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 26 Jun 2024 18:18:44 +0500 Subject: [PATCH 01/67] feat: SDK extension for people to swap --- examples/nodejs/package.json | 1 + examples/nodejs/src/index.ts | 195 +++++++- examples/nodejs/src/types.ts | 58 +++ examples/nodejs/yarn.lock | 891 ++++++++++++++++++++++++++++++++++- 4 files changed, 1133 insertions(+), 12 deletions(-) create mode 100644 examples/nodejs/src/types.ts diff --git a/examples/nodejs/package.json b/examples/nodejs/package.json index 6f98cabe..3c4366de 100644 --- a/examples/nodejs/package.json +++ b/examples/nodejs/package.json @@ -8,6 +8,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { + "@cowprotocol/app-data": "^2.1.0", "@cowprotocol/cow-sdk": "^4.0.3", "ts-node": "^10.9.1" }, diff --git a/examples/nodejs/src/index.ts b/examples/nodejs/src/index.ts index 6e29fef8..96808c85 100644 --- a/examples/nodejs/src/index.ts +++ b/examples/nodejs/src/index.ts @@ -1,16 +1,189 @@ -import { OrderBookApi, SubgraphApi, SupportedChainId } from '@cowprotocol/cow-sdk' +import { + EcdsaSigningScheme, + getQuoteAmountsAndCosts, + OrderBookApi, + OrderCreation, + OrderQuoteRequest, + OrderQuoteSideKindBuy, + OrderQuoteSideKindSell, + OrderSigningUtils, + PriceQuality, + SigningScheme, + SupportedChainId, + type UnsignedOrder, +} from '../../../src' +import { AppDataInfo, AppDataRootSchema, BuildAppDataParams, SwapParameters } from './types' +import { MetadataApi, stringifyDeterministic } from '@cowprotocol/app-data' +import { keccak256, toUtf8Bytes } from 'ethers/lib/utils' +import { ethers } from 'ethers' -// See more examples in /examples/cra -;(async function () { - const orderBookApi = new OrderBookApi({ chainId: SupportedChainId.MAINNET }) - const subgraphApi = new SubgraphApi({ chainId: SupportedChainId.MAINNET }) +const DEFAULT_QUOTE_VALIDITY = 60 * 5 // 5 min + +const SIGN_SCHEME_MAP = { + [EcdsaSigningScheme.EIP712]: SigningScheme.EIP712, + [EcdsaSigningScheme.ETHSIGN]: SigningScheme.ETHSIGN, +} + +const log = (text: string) => console.log(`[SDK] ${text}`) + +async function swapTokens(params: SwapParameters) { + const { + privateKey, + chainId, + from, + sellToken, + sellTokenDecimals, + buyToken, + buyTokenDecimals, + amount, + kind, + slippageBps = 0, + } = params + + log(`Swapping ${amount} ${sellToken} for ${buyToken} on chain ${chainId}`) + + const signer = new ethers.Wallet(privateKey) + + const orderBookApi = new OrderBookApi({ chainId, env: 'staging' }) + + const isSell = kind === 'sell' + const validTo = params.validTo || Math.floor(Date.now() / 1000) + DEFAULT_QUOTE_VALIDITY + const receiver = params.receiver || from + + log('Building app data...') + + const { appDataKeccak256, fullAppData } = await buildAppData({ + chainId, + slippageBps, + orderClass: 'market', + appCode: 'sdk-order', + environment: 'production', + utm: undefined, + }) + + const quoteRequest: OrderQuoteRequest = { + from, + sellToken, + buyToken, + receiver, + validTo, + appData: fullAppData, + appDataHash: appDataKeccak256, + priceQuality: PriceQuality.OPTIMAL, + signingScheme: SigningScheme.EIP712, + ...(isSell + ? { kind: OrderQuoteSideKindSell.SELL, sellAmountBeforeFee: amount } + : { kind: OrderQuoteSideKindBuy.BUY, buyAmountAfterFee: amount }), + } + + log('Getting quote...') + + const { quote, id: quoteId } = await orderBookApi.getQuote(quoteRequest) + + const { afterSlippage } = getQuoteAmountsAndCosts({ + orderParams: quote, + slippagePercentBps: slippageBps, + partnerFeeBps: undefined, // TODO + sellDecimals: sellTokenDecimals, + buyDecimals: buyTokenDecimals, + }) - const order = await orderBookApi.getOrder( - '0xff2e2e54d178997f173266817c1e9ed6fee1a1aae4b43971c53b543cffcc2969845c6f5599fbb25dbdd1b9b013daf85c03f3c63763e4bc4a' - ) + const orderToSign: UnsignedOrder = { + sellToken: quote.sellToken, + buyToken: quote.buyToken, + sellAmount: afterSlippage.sellAmount.toString(), + buyAmount: afterSlippage.buyAmount.toString(), + validTo: quote.validTo, + kind: quote.kind, + partiallyFillable: quote.partiallyFillable, + appData: appDataKeccak256, + receiver, + feeAmount: '0', + } - const lastDaysVolume = await subgraphApi.getTotals() + log('Signing order...') - console.log('[orderBookApi] Order: ', order) - console.log('[subgraphApi] Last day volume: ', lastDaysVolume) + const { signature, signingScheme } = await OrderSigningUtils.signOrder(orderToSign, chainId, signer) + + const orderBody: OrderCreation = { + ...orderToSign, + from, + signature, + signingScheme: SIGN_SCHEME_MAP[signingScheme], + quoteId, + appData: fullAppData, + appDataHash: appDataKeccak256, + } + + log('Posting order...') + + const orderId = await orderBookApi.sendOrder(orderBody) + + log(`Order created, id: ${orderId}`) +} + +async function buildAppData({ + chainId, + slippageBps, + referrerAccount, + appCode, + environment, + orderClass: orderClassName, + utm, + hooks, + widget, + partnerFee, + replacedOrderUid, +}: BuildAppDataParams): Promise { + const metadataApiSDK = new MetadataApi() + + const referrerParams = + referrerAccount && chainId === SupportedChainId.MAINNET ? { address: referrerAccount } : undefined + + const quoteParams = { slippageBips: slippageBps } + const orderClass = { orderClass: orderClassName } + const replacedOrder = replacedOrderUid ? { uid: replacedOrderUid } : undefined + + const doc = await metadataApiSDK.generateAppDataDoc({ + appCode, + environment, + metadata: { + referrer: referrerParams, + quote: quoteParams, + orderClass, + utm, + hooks, + widget, + partnerFee, + ...{ replacedOrder }, + }, + }) + + const { fullAppData, appDataKeccak256 } = await generateAppDataFromDoc(doc) + + return { doc, fullAppData, appDataKeccak256 } +} + +async function generateAppDataFromDoc( + doc: AppDataRootSchema +): Promise> { + const fullAppData = await stringifyDeterministic(doc) + const appDataKeccak256 = keccak256(toUtf8Bytes(fullAppData)) + + return { fullAppData, appDataKeccak256 } +} + +// See more examples in /examples/cra +;(async function () { + swapTokens({ + privateKey: 'xxx', + from: '0xfb3c7eb936cAA12B5A884d612393969A557d4307', + chainId: SupportedChainId.SEPOLIA, + kind: 'sell', + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '120000000000000000', + }) })() diff --git a/examples/nodejs/src/types.ts b/examples/nodejs/src/types.ts new file mode 100644 index 00000000..ada92dc0 --- /dev/null +++ b/examples/nodejs/src/types.ts @@ -0,0 +1,58 @@ +import { latest, LatestAppDataDocVersion } from '@cowprotocol/app-data' +import type { Address, SupportedChainId, CowEnv } from '../../../src' + +export interface SwapParameters { + privateKey: string + chainId: SupportedChainId + from: string + sellToken: Address + sellTokenDecimals: number + buyToken: Address + buyTokenDecimals: number + amount: string + kind: 'sell' | 'buy' + partiallyFillable?: boolean + receiver?: string + deadline?: number + slippageBps?: number + validTo?: number +} + +export type AppDataOrderClass = latest.OrderClass['orderClass'] + +export type AppDataHooks = latest.OrderInteractionHooks + +export type AppDataWidget = latest.Widget + +export type AppDataPartnerFee = latest.PartnerFee + +export type AppDataRootSchema = latest.AppDataRootSchema + +export interface UtmParams { + utmSource?: string + utmMedium?: string + utmCampaign?: string + utmContent?: string + utmTerm?: string +} + +export interface BuildAppDataParams { + appCode: string + environment?: string + chainId: SupportedChainId + slippageBps: number + orderClass: AppDataOrderClass + referrerAccount?: string + utm: UtmParams | undefined + hooks?: AppDataHooks + widget?: AppDataWidget + partnerFee?: AppDataPartnerFee + replacedOrderUid?: string +} + +export interface AppDataInfo { + doc: LatestAppDataDocVersion + fullAppData: string + appDataKeccak256: string + env?: CowEnv +} diff --git a/examples/nodejs/yarn.lock b/examples/nodejs/yarn.lock index 40649d42..607435d9 100644 --- a/examples/nodejs/yarn.lock +++ b/examples/nodejs/yarn.lock @@ -2,6 +2,45 @@ # yarn lockfile v1 +"@assemblyscript/loader@^0.9.4": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.9.4.tgz#a483c54c1253656bb33babd464e3154a173e1577" + integrity sha512-HazVq9zwTVwGmqdwYzu7WyQ6FQVZ7SwET0KKQuKm55jD0IfUpZgN0OPIiZG3zV1iSrVYcN0bdwLRXI/VNCYsUA== + +"@babel/code-frame@^7.0.0": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + dependencies: + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@cowprotocol/app-data@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@cowprotocol/app-data/-/app-data-2.1.0.tgz#55c95e7ffd3fb0dcfecd0fc64a4273955d1d63d1" + integrity sha512-gOlQxng7X5/aQoz2Eg27OegyKgpZVhOEdUQ9cUsc4OnSPal8F4tmLqefKQQWm4Ktaolk7zzh0kiL1vhWxvszmQ== + dependencies: + ajv "^8.11.0" + cross-fetch "^3.1.5" + ipfs-only-hash "^4.0.0" + json-stringify-deterministic "^1.0.8" + multiformats "^9.6.4" + "@cowprotocol/contracts@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@cowprotocol/contracts/-/contracts-1.4.0.tgz#e93e5f25aac76feeaa348fa57231903274676247" @@ -223,6 +262,11 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@multiformats/base-x@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" + integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== + "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" @@ -241,6 +285,59 @@ "@ethersproject/abi" "^5.7.0" ethereum-cryptography "^1.1.2" +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + "@scure/base@~1.1.0": version "1.1.3" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f" @@ -283,6 +380,28 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== +"@types/long@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + +"@types/minimist@^1.2.0": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" + integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== + +"@types/node@>=13.7.0": + version "20.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420" + integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg== + dependencies: + undici-types "~5.26.4" + +"@types/normalize-package-data@^2.4.0": + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" + integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== + acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" @@ -293,16 +412,57 @@ acorn@^8.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== +ajv@^8.11.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.16.0.tgz#22e2a92b94f005f7e0f9c9d39652ef0b8f6f0cb4" + integrity sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw== + dependencies: + fast-deep-equal "^3.1.3" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.4.1" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bl@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273" + integrity sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ== + dependencies: + buffer "^6.0.3" + inherits "^2.0.4" + readable-stream "^3.4.0" + +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -318,6 +478,59 @@ brorand@^1.1.0: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +camelcase-keys@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +cids@^1.0.0, cids@^1.1.5, cids@^1.1.6: + version "1.1.9" + resolved "https://registry.yarnpkg.com/cids/-/cids-1.1.9.tgz#402c26db5c07059377bcd6fb82f2a24e7f2f4a4f" + integrity sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg== + dependencies: + multibase "^4.0.1" + multicodec "^3.0.1" + multihashes "^4.0.1" + uint8arrays "^3.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -337,6 +550,26 @@ cross-fetch@^3.1.5: dependencies: node-fetch "2.6.7" +debug@^4.3.1: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +decamelize-keys@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" + integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -360,6 +593,23 @@ elliptic@6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +err-code@^3.0.0, err-code@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-3.0.1.tgz#a444c7b992705f2b120ee320b09972eef331c920" + integrity sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + ethereum-cryptography@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" @@ -380,6 +630,19 @@ extract-files@^9.0.0: resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== +fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -389,6 +652,11 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + graphql-request@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-4.3.0.tgz#b934e08fcae764aa2cdc697d3c821f046cb5dbf2" @@ -403,6 +671,24 @@ graphql@^16.3.0: resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== +hamt-sharding@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hamt-sharding/-/hamt-sharding-2.0.1.tgz#f45686d0339e74b03b233bee1bde9587727129b6" + integrity sha512-vnjrmdXG9dDs1m/H4iJ6z0JFI2NtgsW5keRkTcM85NGak69Mkf5PHUqBz+Xs0T4sg0ppvj9O5EGAJo40FTxmmA== + dependencies: + sparse-array "^1.3.1" + uint8arrays "^3.0.0" + +hard-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -411,6 +697,13 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -420,21 +713,170 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +hosted-git-info@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== + dependencies: + lru-cache "^6.0.0" + +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -js-sha3@0.8.0: +interface-ipld-format@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/interface-ipld-format/-/interface-ipld-format-1.0.1.tgz#bee39c70c584a033e186ff057a2be89f215963e3" + integrity sha512-WV/ar+KQJVoQpqRDYdo7YPGYIUHJxCuOEhdvsRpzLqoOIVCqPKdMMYmsLL1nCRsF3yYNio+PAJbCKiv6drrEAg== + dependencies: + cids "^1.1.6" + multicodec "^3.0.1" + multihashes "^4.0.2" + +ipfs-only-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ipfs-only-hash/-/ipfs-only-hash-4.0.0.tgz#b3bd60a244d9eb7394961aa9d812a2e5ac7c04d6" + integrity sha512-TE1DZCvfw8i3gcsTq3P4TFx3cKFJ3sluu/J3XINkJhIN9OwJgNMqKA+WnKx6ByCb1IoPXsTp1KM7tupElb6SyA== + dependencies: + ipfs-unixfs-importer "^7.0.1" + meow "^9.0.0" + +ipfs-unixfs-importer@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ipfs-unixfs-importer/-/ipfs-unixfs-importer-7.0.3.tgz#b850e831ca9647d589ef50bc33421f65bab7bba6" + integrity sha512-qeFOlD3AQtGzr90sr5Tq1Bi8pT5Nr2tSI8z310m7R4JDYgZc6J1PEZO3XZQ8l1kuGoqlAppBZuOYmPEqaHcVQQ== + dependencies: + bl "^5.0.0" + cids "^1.1.5" + err-code "^3.0.1" + hamt-sharding "^2.0.0" + ipfs-unixfs "^4.0.3" + ipld-dag-pb "^0.22.2" + it-all "^1.0.5" + it-batch "^1.0.8" + it-first "^1.0.6" + it-parallel-batch "^1.0.9" + merge-options "^3.0.4" + multihashing-async "^2.1.0" + rabin-wasm "^0.1.4" + uint8arrays "^2.1.2" + +ipfs-unixfs@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/ipfs-unixfs/-/ipfs-unixfs-4.0.3.tgz#7c43e5726052ade4317245358ac541ef3d63d94e" + integrity sha512-hzJ3X4vlKT8FQ3Xc4M1szaFVjsc1ZydN+E4VQ91aXxfpjFn9G2wsMo1EFdAXNq/BUnN5dgqIOMP5zRYr3DTsAw== + dependencies: + err-code "^3.0.1" + protobufjs "^6.10.2" + +ipld-dag-pb@^0.22.2: + version "0.22.3" + resolved "https://registry.yarnpkg.com/ipld-dag-pb/-/ipld-dag-pb-0.22.3.tgz#6d5af28b5752236a5cb0e0a1888c87dd733b55cd" + integrity sha512-dfG5C5OVAR4FEP7Al2CrHWvAyIM7UhAQrjnOYOIxXGQz5NlEj6wGX0XQf6Ru6or1na6upvV3NQfstapQG8X2rg== + dependencies: + cids "^1.0.0" + interface-ipld-format "^1.0.0" + multicodec "^3.0.1" + multihashing-async "^2.0.0" + protobufjs "^6.10.2" + stable "^0.1.8" + uint8arrays "^2.0.5" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-core-module@^2.13.0, is-core-module@^2.5.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" + integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== + dependencies: + hasown "^2.0.2" + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +it-all@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/it-all/-/it-all-1.0.6.tgz#852557355367606295c4c3b7eff0136f07749335" + integrity sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A== + +it-batch@^1.0.8, it-batch@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/it-batch/-/it-batch-1.0.9.tgz#7e95aaacb3f9b1b8ca6c8b8367892171d6a5b37f" + integrity sha512-7Q7HXewMhNFltTsAMdSz6luNhyhkhEtGGbYek/8Xb/GiqYMtwUmopE1ocPSiJKKp3rM4Dt045sNFoUu+KZGNyA== + +it-first@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/it-first/-/it-first-1.0.7.tgz#a4bef40da8be21667f7d23e44dae652f5ccd7ab1" + integrity sha512-nvJKZoBpZD/6Rtde6FXqwDqDZGF1sCADmr2Zoc0hZsIvnE449gRFnGctxDf09Bzc/FWnHXAdaHVIetY6lrE0/g== + +it-parallel-batch@^1.0.9: + version "1.0.11" + resolved "https://registry.yarnpkg.com/it-parallel-batch/-/it-parallel-batch-1.0.11.tgz#f889b4e1c7a62ef24111dbafbaaa010b33d00f69" + integrity sha512-UWsWHv/kqBpMRmyZJzlmZeoAMA0F3SZr08FBdbhtbe+MtoEBgr/ZUAKrnenhXCBrsopy76QjRH2K/V8kNdupbQ== + dependencies: + it-batch "^1.0.9" + +js-sha3@0.8.0, js-sha3@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stringify-deterministic@^1.0.8: + version "1.0.12" + resolved "https://registry.yarnpkg.com/json-stringify-deterministic/-/json-stringify-deterministic-1.0.12.tgz#aaa3f907466ed01e3afd77b898d0a2b3b132820a" + integrity sha512-q3PN0lbUdv0pmurkBNdJH3pfFvOTL/Zp0lquqpvcjfKzt6Y0j49EPHAmVHCAS4Ceq/Y+PejWTzyiVpoY71+D6g== + just-performance@4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/just-performance/-/just-performance-4.3.0.tgz#cc2bc8c9227f09e97b6b1df4cd0de2df7ae16db1" integrity sha512-L7RjvtJsL0QO8xFs5wEoDDzzJwoiowRw6Rn/GnvldlchS2JQr9wFYPiwZcDfrbbujEKqKN0tvENdbjXdYhDp5Q== +kind-of@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + limiter@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/limiter/-/limiter-2.1.0.tgz#d38d7c5b63729bb84fb0c4d8594b7e955a5182a2" @@ -442,11 +884,70 @@ limiter@^2.1.0: dependencies: just-performance "4.3.0" +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +long@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== + +map-obj@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== + +meow@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize "^1.2.0" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -459,6 +960,11 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -469,6 +975,71 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== +minimist-options@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" + integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + kind-of "^6.0.3" + +minimist@^1.2.5: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +multibase@^4.0.1: + version "4.0.6" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.6.tgz#6e624341483d6123ca1ede956208cb821b440559" + integrity sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ== + dependencies: + "@multiformats/base-x" "^4.0.1" + +multicodec@^3.0.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-3.2.1.tgz#82de3254a0fb163a107c1aab324f2a91ef51efb2" + integrity sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw== + dependencies: + uint8arrays "^3.0.0" + varint "^6.0.0" + +multiformats@^9.4.2, multiformats@^9.6.4: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== + +multihashes@^4.0.1, multihashes@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-4.0.3.tgz#426610539cd2551edbf533adeac4c06b3b90fb05" + integrity sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA== + dependencies: + multibase "^4.0.1" + uint8arrays "^3.0.0" + varint "^5.0.2" + +multihashing-async@^2.0.0, multihashing-async@^2.1.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/multihashing-async/-/multihashing-async-2.1.4.tgz#26dce2ec7a40f0e7f9e732fc23ca5f564d693843" + integrity sha512-sB1MiQXPSBTNRVSJc2zM157PXgDtud2nMFUEIvBrsq5Wv96sUclMRK/ecjoP1T/W61UJBqt4tCTwMkUpt2Gbzg== + dependencies: + blakejs "^1.1.0" + err-code "^3.0.0" + js-sha3 "^0.8.0" + multihashes "^4.0.1" + murmurhash3js-revisited "^3.0.0" + uint8arrays "^3.0.0" + +murmurhash3js-revisited@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz#6bd36e25de8f73394222adc6e41fa3fac08a5869" + integrity sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g== + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -476,11 +1047,255 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.1: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-package-data@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" + integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== + dependencies: + hosted-git-info "^4.0.1" + is-core-module "^2.5.0" + semver "^7.3.4" + validate-npm-package-license "^3.0.1" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +protobufjs@^6.10.2: + version "6.11.4" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" + integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" ">=13.7.0" + long "^4.0.0" + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== + +rabin-wasm@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/rabin-wasm/-/rabin-wasm-0.1.5.tgz#5b625ca007d6a2cbc1456c78ae71d550addbc9c9" + integrity sha512-uWgQTo7pim1Rnj5TuWcCewRDTf0PEFTSlaUjWP4eY9EbLV9em08v89oCz/WO+wRxpYuO36XEHp4wgYQnAgOHzA== + dependencies: + "@assemblyscript/loader" "^0.9.4" + bl "^5.0.0" + debug "^4.3.1" + minimist "^1.2.5" + node-fetch "^2.6.1" + readable-stream "^3.6.0" + +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve@^1.10.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"semver@2 || 3 || 4 || 5": + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^7.3.4: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + +sparse-array@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/sparse-array/-/sparse-array-1.3.2.tgz#0e1a8b71706d356bc916fe754ff496d450ec20b0" + integrity sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg== + +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.18" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" + integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +trim-newlines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" + integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== + ts-node@^10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -500,11 +1315,75 @@ ts-node@^10.9.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +type-fest@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" + integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +uint8arrays@^2.0.5, uint8arrays@^2.1.2: + version "2.1.10" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a" + integrity sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A== + dependencies: + multiformats "^9.4.2" + +uint8arrays@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" + integrity sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg== + dependencies: + multiformats "^9.4.2" + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +uri-js@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +varint@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== + +varint@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" + integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -518,6 +1397,16 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^20.2.3: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" From e8927e2d1ee2442653c993cc4f2a4368ef1db973 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 26 Jun 2024 19:41:11 +0500 Subject: [PATCH 02/67] feat: SDK extension for people to trade --- examples/nodejs/src/appDataUtils.ts | 35 ++++ examples/nodejs/src/consts.ts | 10 ++ examples/nodejs/src/index.ts | 231 +++++++------------------- examples/nodejs/src/postLimitOrder.ts | 50 ++++++ examples/nodejs/src/postSwapOrder.ts | 82 +++++++++ examples/nodejs/src/postTrade.ts | 93 +++++++++++ examples/nodejs/src/types.ts | 63 +++---- 7 files changed, 360 insertions(+), 204 deletions(-) create mode 100644 examples/nodejs/src/appDataUtils.ts create mode 100644 examples/nodejs/src/consts.ts create mode 100644 examples/nodejs/src/postLimitOrder.ts create mode 100644 examples/nodejs/src/postSwapOrder.ts create mode 100644 examples/nodejs/src/postTrade.ts diff --git a/examples/nodejs/src/appDataUtils.ts b/examples/nodejs/src/appDataUtils.ts new file mode 100644 index 00000000..6c4d9f2a --- /dev/null +++ b/examples/nodejs/src/appDataUtils.ts @@ -0,0 +1,35 @@ +import { AppDataInfo, AppDataRootSchema, BuildAppDataParams } from './types' +import { AppDataParams, MetadataApi, stringifyDeterministic } from '@cowprotocol/app-data' +import { keccak256, toUtf8Bytes } from 'ethers/lib/utils' + +export async function buildAppData( + { slippageBps, appCode, orderClass: orderClassName }: BuildAppDataParams, + advancedParams?: AppDataParams +): Promise { + const metadataApiSDK = new MetadataApi() + + const quoteParams = { slippageBips: slippageBps } + const orderClass = { orderClass: orderClassName } + + const doc = await metadataApiSDK.generateAppDataDoc({ + appCode, + metadata: { + quote: quoteParams, + orderClass, + }, + ...advancedParams, + }) + + const { fullAppData, appDataKeccak256 } = await generateAppDataFromDoc(doc) + + return { doc, fullAppData, appDataKeccak256 } +} + +export async function generateAppDataFromDoc( + doc: AppDataRootSchema +): Promise> { + const fullAppData = await stringifyDeterministic(doc) + const appDataKeccak256 = keccak256(toUtf8Bytes(fullAppData)) + + return { fullAppData, appDataKeccak256 } +} diff --git a/examples/nodejs/src/consts.ts b/examples/nodejs/src/consts.ts new file mode 100644 index 00000000..693f79f9 --- /dev/null +++ b/examples/nodejs/src/consts.ts @@ -0,0 +1,10 @@ +import { EcdsaSigningScheme, SigningScheme } from '../../../src' + +export const log = (text: string) => console.log(`[SDK] ${text}`) + +export const DEFAULT_QUOTE_VALIDITY = 60 * 10 // 10 min + +export const SIGN_SCHEME_MAP = { + [EcdsaSigningScheme.EIP712]: SigningScheme.EIP712, + [EcdsaSigningScheme.ETHSIGN]: SigningScheme.ETHSIGN, +} diff --git a/examples/nodejs/src/index.ts b/examples/nodejs/src/index.ts index 96808c85..1dce83ae 100644 --- a/examples/nodejs/src/index.ts +++ b/examples/nodejs/src/index.ts @@ -1,189 +1,70 @@ -import { - EcdsaSigningScheme, - getQuoteAmountsAndCosts, - OrderBookApi, - OrderCreation, - OrderQuoteRequest, - OrderQuoteSideKindBuy, - OrderQuoteSideKindSell, - OrderSigningUtils, - PriceQuality, - SigningScheme, - SupportedChainId, - type UnsignedOrder, -} from '../../../src' -import { AppDataInfo, AppDataRootSchema, BuildAppDataParams, SwapParameters } from './types' -import { MetadataApi, stringifyDeterministic } from '@cowprotocol/app-data' -import { keccak256, toUtf8Bytes } from 'ethers/lib/utils' -import { ethers } from 'ethers' +import { OrderKind, SupportedChainId } from '../../../src' +import { postSwapOrder } from './postSwapOrder' +import { postLimitOrder } from './postLimitOrder' -const DEFAULT_QUOTE_VALIDITY = 60 * 5 // 5 min +const privateKey = 'xxx' -const SIGN_SCHEME_MAP = { - [EcdsaSigningScheme.EIP712]: SigningScheme.EIP712, - [EcdsaSigningScheme.ETHSIGN]: SigningScheme.ETHSIGN, -} - -const log = (text: string) => console.log(`[SDK] ${text}`) - -async function swapTokens(params: SwapParameters) { - const { - privateKey, - chainId, - from, - sellToken, - sellTokenDecimals, - buyToken, - buyTokenDecimals, - amount, - kind, - slippageBps = 0, - } = params - - log(`Swapping ${amount} ${sellToken} for ${buyToken} on chain ${chainId}`) - - const signer = new ethers.Wallet(privateKey) - - const orderBookApi = new OrderBookApi({ chainId, env: 'staging' }) - - const isSell = kind === 'sell' - const validTo = params.validTo || Math.floor(Date.now() / 1000) + DEFAULT_QUOTE_VALIDITY - const receiver = params.receiver || from - - log('Building app data...') - - const { appDataKeccak256, fullAppData } = await buildAppData({ - chainId, - slippageBps, - orderClass: 'market', - appCode: 'sdk-order', - environment: 'production', - utm: undefined, - }) - - const quoteRequest: OrderQuoteRequest = { - from, - sellToken, - buyToken, - receiver, - validTo, - appData: fullAppData, - appDataHash: appDataKeccak256, - priceQuality: PriceQuality.OPTIMAL, - signingScheme: SigningScheme.EIP712, - ...(isSell - ? { kind: OrderQuoteSideKindSell.SELL, sellAmountBeforeFee: amount } - : { kind: OrderQuoteSideKindBuy.BUY, buyAmountAfterFee: amount }), - } - - log('Getting quote...') - - const { quote, id: quoteId } = await orderBookApi.getQuote(quoteRequest) - - const { afterSlippage } = getQuoteAmountsAndCosts({ - orderParams: quote, - slippagePercentBps: slippageBps, - partnerFeeBps: undefined, // TODO - sellDecimals: sellTokenDecimals, - buyDecimals: buyTokenDecimals, - }) - - const orderToSign: UnsignedOrder = { - sellToken: quote.sellToken, - buyToken: quote.buyToken, - sellAmount: afterSlippage.sellAmount.toString(), - buyAmount: afterSlippage.buyAmount.toString(), - validTo: quote.validTo, - kind: quote.kind, - partiallyFillable: quote.partiallyFillable, - appData: appDataKeccak256, - receiver, - feeAmount: '0', - } - - log('Signing order...') - - const { signature, signingScheme } = await OrderSigningUtils.signOrder(orderToSign, chainId, signer) - - const orderBody: OrderCreation = { - ...orderToSign, - from, - signature, - signingScheme: SIGN_SCHEME_MAP[signingScheme], - quoteId, - appData: fullAppData, - appDataHash: appDataKeccak256, - } - - log('Posting order...') - - const orderId = await orderBookApi.sendOrder(orderBody) - - log(`Order created, id: ${orderId}`) -} - -async function buildAppData({ - chainId, - slippageBps, - referrerAccount, - appCode, - environment, - orderClass: orderClassName, - utm, - hooks, - widget, - partnerFee, - replacedOrderUid, -}: BuildAppDataParams): Promise { - const metadataApiSDK = new MetadataApi() - - const referrerParams = - referrerAccount && chainId === SupportedChainId.MAINNET ? { address: referrerAccount } : undefined +// Swap +;(async function () { + return - const quoteParams = { slippageBips: slippageBps } - const orderClass = { orderClass: orderClassName } - const replacedOrder = replacedOrderUid ? { uid: replacedOrderUid } : undefined + postSwapOrder({ + appCode: 'cow-sdk-example', + signer: privateKey, + chainId: SupportedChainId.SEPOLIA, - const doc = await metadataApiSDK.generateAppDataDoc({ - appCode, - environment, - metadata: { - referrer: referrerParams, - quote: quoteParams, - orderClass, - utm, - hooks, - widget, - partnerFee, - ...{ replacedOrder }, - }, + kind: OrderKind.SELL, + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '120000000000000000', }) +})() - const { fullAppData, appDataKeccak256 } = await generateAppDataFromDoc(doc) - - return { doc, fullAppData, appDataKeccak256 } -} - -async function generateAppDataFromDoc( - doc: AppDataRootSchema -): Promise> { - const fullAppData = await stringifyDeterministic(doc) - const appDataKeccak256 = keccak256(toUtf8Bytes(fullAppData)) - - return { fullAppData, appDataKeccak256 } -} - -// See more examples in /examples/cra +// Limit order ;(async function () { - swapTokens({ - privateKey: 'xxx', - from: '0xfb3c7eb936cAA12B5A884d612393969A557d4307', + return + + postLimitOrder({ + appCode: 'cow-sdk-example', + signer: privateKey, chainId: SupportedChainId.SEPOLIA, - kind: 'sell', + + kind: OrderKind.BUY, sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', sellTokenDecimals: 18, buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', buyTokenDecimals: 18, - amount: '120000000000000000', + sellAmount: '120000000000000000', + buyAmount: '66600000000000000000', }) })() + +// Swap with partner fee +;(async function () { + postSwapOrder( + { + appCode: 'cow-sdk-example', + signer: privateKey, + chainId: SupportedChainId.SEPOLIA, + + kind: OrderKind.SELL, + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '120000000000000000', + }, + { + appData: { + metadata: { + partnerFee: { + bps: 100, + recipient: '0xfb3c7eb936cAA12B5A884d612393969A557d4307', + }, + }, + }, + } + ) +})() diff --git a/examples/nodejs/src/postLimitOrder.ts b/examples/nodejs/src/postLimitOrder.ts new file mode 100644 index 00000000..0f277418 --- /dev/null +++ b/examples/nodejs/src/postLimitOrder.ts @@ -0,0 +1,50 @@ +import { LimitOrderAdvancedSettings, LimitOrderParameters } from './types' +import { log } from './consts' +import { ethers } from 'ethers' +import { OrderBookApi } from '../../../src' +import { buildAppData } from './appDataUtils' +import { postCoWProtocolTrade } from './postTrade' + +export async function postLimitOrder(params: LimitOrderParameters, advancedSettings?: LimitOrderAdvancedSettings) { + const { + appCode, + chainId, + sellToken, + buyToken, + sellAmount, + buyAmount, + quoteId, + slippageBps = 0, + env = 'prod', + } = params + + log(`Limit order ${sellAmount} ${sellToken} for ${buyAmount} ${buyToken} on chain ${chainId}`) + + const signer = typeof params.signer === 'string' ? new ethers.Wallet(params.signer) : params.signer + const orderBookApi = new OrderBookApi({ chainId, env }) + const feeAmount = '0' + + log('Building app data...') + + const appDataInfo = await buildAppData( + { + slippageBps, + orderClass: 'limit', + appCode, + }, + advancedSettings?.appData + ) + + await postCoWProtocolTrade( + orderBookApi, + signer, + appDataInfo, + { + ...params, + quoteId, + sellAmount, + buyAmount, + }, + feeAmount + ) +} diff --git a/examples/nodejs/src/postSwapOrder.ts b/examples/nodejs/src/postSwapOrder.ts new file mode 100644 index 00000000..1cf308e1 --- /dev/null +++ b/examples/nodejs/src/postSwapOrder.ts @@ -0,0 +1,82 @@ +import { SwapAdvancedSettings, SwapParameters } from './types' +import { DEFAULT_QUOTE_VALIDITY, log } from './consts' +import { ethers } from 'ethers' +import { + OrderBookApi, + OrderQuoteRequest, + OrderQuoteSideKindBuy, + OrderQuoteSideKindSell, + PriceQuality, + SigningScheme, +} from '../../../src' +import { buildAppData } from './appDataUtils' +import { postCoWProtocolTrade } from './postTrade' + +export async function postSwapOrder(params: SwapParameters, advancedSettings?: SwapAdvancedSettings) { + const { + appCode, + chainId, + sellToken, + buyToken, + amount, + kind, + validFor = DEFAULT_QUOTE_VALIDITY, + slippageBps = 0, + env = 'prod', + } = params + + log(`Swap ${amount} ${sellToken} for ${buyToken} on chain ${chainId}`) + + const signer = typeof params.signer === 'string' ? new ethers.Wallet(params.signer) : params.signer + const orderBookApi = new OrderBookApi({ chainId, env }) + + const from = await signer.getAddress() + const receiver = params.receiver || from + const isSell = kind === 'sell' + + log('Building app data...') + + const appDataInfo = await buildAppData( + { + slippageBps, + orderClass: 'market', + appCode, + }, + advancedSettings?.appData + ) + + const { appDataKeccak256, fullAppData } = appDataInfo + + const quoteRequest: OrderQuoteRequest = { + from, + sellToken, + buyToken, + receiver, + validFor, + appData: fullAppData, + appDataHash: appDataKeccak256, + priceQuality: PriceQuality.OPTIMAL, + signingScheme: SigningScheme.EIP712, + ...(isSell + ? { kind: OrderQuoteSideKindSell.SELL, sellAmountBeforeFee: amount } + : { kind: OrderQuoteSideKindBuy.BUY, buyAmountAfterFee: amount }), + ...advancedSettings?.quoteRequest, + } + + log('Getting quote...') + + const { quote, id: quoteId } = await orderBookApi.getQuote(quoteRequest) + + await postCoWProtocolTrade( + orderBookApi, + signer, + appDataInfo, + { + ...params, + quoteId, + sellAmount: quote.sellAmount, + buyAmount: quote.buyAmount, + }, + quote.feeAmount + ) +} diff --git a/examples/nodejs/src/postTrade.ts b/examples/nodejs/src/postTrade.ts new file mode 100644 index 00000000..ea60d20b --- /dev/null +++ b/examples/nodejs/src/postTrade.ts @@ -0,0 +1,93 @@ +import { + getQuoteAmountsAndCosts, + OrderBookApi, + OrderCreation, + OrderSigningUtils, + type UnsignedOrder, +} from '../../../src' +import { ethers } from 'ethers' +import { AppDataInfo, LimitOrderParameters } from './types' +import { DEFAULT_QUOTE_VALIDITY, log, SIGN_SCHEME_MAP } from './consts' + +export async function postCoWProtocolTrade( + orderBookApi: OrderBookApi, + signer: ethers.Signer, + appData: AppDataInfo, + params: LimitOrderParameters, + feeAmount: string +): Promise { + const { + chainId, + sellToken, + sellTokenDecimals, + buyToken, + buyTokenDecimals, + sellAmount, + buyAmount, + kind, + partiallyFillable = false, + quoteId = null, + validFor, + slippageBps = 0, + } = params + + const validTo = params.validTo || Math.floor(Date.now() / 1000) + (validFor || DEFAULT_QUOTE_VALIDITY) + const from = await signer.getAddress() + const receiver = params.receiver || from + const { appDataKeccak256, fullAppData, doc } = appData + const partnerFeeBps = doc?.metadata?.partnerFee?.bps + + const { afterSlippage } = getQuoteAmountsAndCosts({ + orderParams: { + sellToken, + buyToken, + sellAmount, + buyAmount, + receiver, + validTo, + kind, + feeAmount, + appData: appDataKeccak256, + partiallyFillable, + }, + slippagePercentBps: slippageBps, + partnerFeeBps, + sellDecimals: sellTokenDecimals, + buyDecimals: buyTokenDecimals, + }) + + const orderToSign: UnsignedOrder = { + sellToken, + buyToken, + sellAmount: afterSlippage.sellAmount.toString(), + buyAmount: afterSlippage.buyAmount.toString(), + validTo, + kind, + partiallyFillable, + appData: appDataKeccak256, + receiver, + feeAmount: '0', + } + + log('Signing order...') + + const { signature, signingScheme } = await OrderSigningUtils.signOrder(orderToSign, chainId, signer) + + const orderBody: OrderCreation = { + ...orderToSign, + from, + signature, + signingScheme: SIGN_SCHEME_MAP[signingScheme], + quoteId, + appData: fullAppData, + appDataHash: appDataKeccak256, + } + + log('Posting order...') + + const orderId = await orderBookApi.sendOrder(orderBody) + + log(`Order created, id: ${orderId}`) + + return orderId +} diff --git a/examples/nodejs/src/types.ts b/examples/nodejs/src/types.ts index ada92dc0..f93eb5d9 100644 --- a/examples/nodejs/src/types.ts +++ b/examples/nodejs/src/types.ts @@ -1,53 +1,58 @@ -import { latest, LatestAppDataDocVersion } from '@cowprotocol/app-data' -import type { Address, SupportedChainId, CowEnv } from '../../../src' +import { latest, LatestAppDataDocVersion, AppDataParams } from '@cowprotocol/app-data' +import { Address, SupportedChainId, CowEnv, OrderQuoteRequest, OrderKind } from '../../../src' +import type { Signer } from '@ethersproject/abstract-signer' -export interface SwapParameters { - privateKey: string - chainId: SupportedChainId - from: string +export interface TradeBaseParameters { + kind: OrderKind sellToken: Address sellTokenDecimals: number buyToken: Address buyTokenDecimals: number amount: string - kind: 'sell' | 'buy' +} + +export interface TradeOptionalParameters { + env?: CowEnv partiallyFillable?: boolean - receiver?: string - deadline?: number slippageBps?: number - validTo?: number + receiver?: string + validFor?: number } -export type AppDataOrderClass = latest.OrderClass['orderClass'] +export interface TraderParameters { + chainId: SupportedChainId + signer: Signer | string + appCode: string +} -export type AppDataHooks = latest.OrderInteractionHooks +export interface TradeParameters extends TradeBaseParameters, TradeOptionalParameters {} -export type AppDataWidget = latest.Widget +export interface SwapParameters extends TraderParameters, TradeParameters {} -export type AppDataPartnerFee = latest.PartnerFee +export interface LimitOrderParameters extends TraderParameters, Omit { + sellAmount: string + buyAmount: string + validTo?: number + quoteId?: number +} -export type AppDataRootSchema = latest.AppDataRootSchema +export interface SwapAdvancedSettings { + quoteRequest?: Partial> + appData?: AppDataParams +} -export interface UtmParams { - utmSource?: string - utmMedium?: string - utmCampaign?: string - utmContent?: string - utmTerm?: string +export interface LimitOrderAdvancedSettings { + appData?: AppDataParams } +export type AppDataOrderClass = latest.OrderClass['orderClass'] + +export type AppDataRootSchema = latest.AppDataRootSchema + export interface BuildAppDataParams { appCode: string - environment?: string - chainId: SupportedChainId slippageBps: number orderClass: AppDataOrderClass - referrerAccount?: string - utm: UtmParams | undefined - hooks?: AppDataHooks - widget?: AppDataWidget - partnerFee?: AppDataPartnerFee - replacedOrderUid?: string } export interface AppDataInfo { From 59f550b13949147328dfe97664f235ffa33c3323 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 27 Jun 2024 13:19:56 +0500 Subject: [PATCH 03/67] refactor: move files to trading dir --- examples/nodejs/package.json | 1 - examples/nodejs/src/index.ts | 4 +- examples/nodejs/yarn.lock | 891 +----------------- examples/vanilla/src/index.ts | 5 +- package.json | 3 +- src/index.ts | 1 + .../src => src/trading}/appDataUtils.ts | 0 .../nodejs/src => src/trading}/consts.ts | 2 +- src/trading/index.ts | 2 + .../src => src/trading}/postLimitOrder.ts | 2 +- .../src => src/trading}/postSwapOrder.ts | 2 +- .../nodejs/src => src/trading}/postTrade.ts | 9 +- {examples/nodejs/src => src/trading}/types.ts | 3 +- yarn.lock | 629 ++++++++++++- 14 files changed, 640 insertions(+), 914 deletions(-) rename {examples/nodejs/src => src/trading}/appDataUtils.ts (100%) rename {examples/nodejs/src => src/trading}/consts.ts (80%) create mode 100644 src/trading/index.ts rename {examples/nodejs/src => src/trading}/postLimitOrder.ts (96%) rename {examples/nodejs/src => src/trading}/postSwapOrder.ts (98%) rename {examples/nodejs/src => src/trading}/postTrade.ts (93%) rename {examples/nodejs/src => src/trading}/types.ts (92%) diff --git a/examples/nodejs/package.json b/examples/nodejs/package.json index 3c4366de..6f98cabe 100644 --- a/examples/nodejs/package.json +++ b/examples/nodejs/package.json @@ -8,7 +8,6 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "@cowprotocol/app-data": "^2.1.0", "@cowprotocol/cow-sdk": "^4.0.3", "ts-node": "^10.9.1" }, diff --git a/examples/nodejs/src/index.ts b/examples/nodejs/src/index.ts index 1dce83ae..76ee3561 100644 --- a/examples/nodejs/src/index.ts +++ b/examples/nodejs/src/index.ts @@ -1,6 +1,4 @@ -import { OrderKind, SupportedChainId } from '../../../src' -import { postSwapOrder } from './postSwapOrder' -import { postLimitOrder } from './postLimitOrder' +import { SupportedChainId, OrderKind, postSwapOrder, postLimitOrder } from '../../../src' const privateKey = 'xxx' diff --git a/examples/nodejs/yarn.lock b/examples/nodejs/yarn.lock index 607435d9..40649d42 100644 --- a/examples/nodejs/yarn.lock +++ b/examples/nodejs/yarn.lock @@ -2,45 +2,6 @@ # yarn lockfile v1 -"@assemblyscript/loader@^0.9.4": - version "0.9.4" - resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.9.4.tgz#a483c54c1253656bb33babd464e3154a173e1577" - integrity sha512-HazVq9zwTVwGmqdwYzu7WyQ6FQVZ7SwET0KKQuKm55jD0IfUpZgN0OPIiZG3zV1iSrVYcN0bdwLRXI/VNCYsUA== - -"@babel/code-frame@^7.0.0": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== - dependencies: - "@babel/highlight" "^7.24.7" - picocolors "^1.0.0" - -"@babel/helper-validator-identifier@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" - integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== - -"@babel/highlight@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" - integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== - dependencies: - "@babel/helper-validator-identifier" "^7.24.7" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@cowprotocol/app-data@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@cowprotocol/app-data/-/app-data-2.1.0.tgz#55c95e7ffd3fb0dcfecd0fc64a4273955d1d63d1" - integrity sha512-gOlQxng7X5/aQoz2Eg27OegyKgpZVhOEdUQ9cUsc4OnSPal8F4tmLqefKQQWm4Ktaolk7zzh0kiL1vhWxvszmQ== - dependencies: - ajv "^8.11.0" - cross-fetch "^3.1.5" - ipfs-only-hash "^4.0.0" - json-stringify-deterministic "^1.0.8" - multiformats "^9.6.4" - "@cowprotocol/contracts@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@cowprotocol/contracts/-/contracts-1.4.0.tgz#e93e5f25aac76feeaa348fa57231903274676247" @@ -262,11 +223,6 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@multiformats/base-x@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" - integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== - "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" @@ -285,59 +241,6 @@ "@ethersproject/abi" "^5.7.0" ethereum-cryptography "^1.1.2" -"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" - integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== - -"@protobufjs/base64@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" - integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== - -"@protobufjs/codegen@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" - integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== - -"@protobufjs/eventemitter@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" - integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== - -"@protobufjs/fetch@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" - integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== - dependencies: - "@protobufjs/aspromise" "^1.1.1" - "@protobufjs/inquire" "^1.1.0" - -"@protobufjs/float@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" - integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== - -"@protobufjs/inquire@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" - integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== - -"@protobufjs/path@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" - integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== - -"@protobufjs/pool@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" - integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== - -"@protobufjs/utf8@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" - integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== - "@scure/base@~1.1.0": version "1.1.3" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f" @@ -380,28 +283,6 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== -"@types/long@^4.0.1": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" - integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== - -"@types/minimist@^1.2.0": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" - integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== - -"@types/node@>=13.7.0": - version "20.14.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420" - integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg== - dependencies: - undici-types "~5.26.4" - -"@types/normalize-package-data@^2.4.0": - version "2.4.4" - resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" - integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== - acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" @@ -412,57 +293,16 @@ acorn@^8.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== -ajv@^8.11.0: - version "8.16.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.16.0.tgz#22e2a92b94f005f7e0f9c9d39652ef0b8f6f0cb4" - integrity sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw== - dependencies: - fast-deep-equal "^3.1.3" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.4.1" - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -bl@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273" - integrity sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ== - dependencies: - buffer "^6.0.3" - inherits "^2.0.4" - readable-stream "^3.4.0" - -blakejs@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" - integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== - bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -478,59 +318,6 @@ brorand@^1.1.0: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - -camelcase-keys@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" - integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== - dependencies: - camelcase "^5.3.1" - map-obj "^4.0.0" - quick-lru "^4.0.1" - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -cids@^1.0.0, cids@^1.1.5, cids@^1.1.6: - version "1.1.9" - resolved "https://registry.yarnpkg.com/cids/-/cids-1.1.9.tgz#402c26db5c07059377bcd6fb82f2a24e7f2f4a4f" - integrity sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg== - dependencies: - multibase "^4.0.1" - multicodec "^3.0.1" - multihashes "^4.0.1" - uint8arrays "^3.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -550,26 +337,6 @@ cross-fetch@^3.1.5: dependencies: node-fetch "2.6.7" -debug@^4.3.1: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== - dependencies: - ms "2.1.2" - -decamelize-keys@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" - integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== - dependencies: - decamelize "^1.1.0" - map-obj "^1.0.0" - -decamelize@^1.1.0, decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -593,23 +360,6 @@ elliptic@6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -err-code@^3.0.0, err-code@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/err-code/-/err-code-3.0.1.tgz#a444c7b992705f2b120ee320b09972eef331c920" - integrity sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - ethereum-cryptography@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" @@ -630,19 +380,6 @@ extract-files@^9.0.0: resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== -fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -652,11 +389,6 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - graphql-request@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-4.3.0.tgz#b934e08fcae764aa2cdc697d3c821f046cb5dbf2" @@ -671,24 +403,6 @@ graphql@^16.3.0: resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== -hamt-sharding@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/hamt-sharding/-/hamt-sharding-2.0.1.tgz#f45686d0339e74b03b233bee1bde9587727129b6" - integrity sha512-vnjrmdXG9dDs1m/H4iJ6z0JFI2NtgsW5keRkTcM85NGak69Mkf5PHUqBz+Xs0T4sg0ppvj9O5EGAJo40FTxmmA== - dependencies: - sparse-array "^1.3.1" - uint8arrays "^3.0.0" - -hard-rejection@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" - integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -697,13 +411,6 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -713,170 +420,21 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - -hosted-git-info@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" - integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== - dependencies: - lru-cache "^6.0.0" - -ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -interface-ipld-format@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/interface-ipld-format/-/interface-ipld-format-1.0.1.tgz#bee39c70c584a033e186ff057a2be89f215963e3" - integrity sha512-WV/ar+KQJVoQpqRDYdo7YPGYIUHJxCuOEhdvsRpzLqoOIVCqPKdMMYmsLL1nCRsF3yYNio+PAJbCKiv6drrEAg== - dependencies: - cids "^1.1.6" - multicodec "^3.0.1" - multihashes "^4.0.2" - -ipfs-only-hash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ipfs-only-hash/-/ipfs-only-hash-4.0.0.tgz#b3bd60a244d9eb7394961aa9d812a2e5ac7c04d6" - integrity sha512-TE1DZCvfw8i3gcsTq3P4TFx3cKFJ3sluu/J3XINkJhIN9OwJgNMqKA+WnKx6ByCb1IoPXsTp1KM7tupElb6SyA== - dependencies: - ipfs-unixfs-importer "^7.0.1" - meow "^9.0.0" - -ipfs-unixfs-importer@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ipfs-unixfs-importer/-/ipfs-unixfs-importer-7.0.3.tgz#b850e831ca9647d589ef50bc33421f65bab7bba6" - integrity sha512-qeFOlD3AQtGzr90sr5Tq1Bi8pT5Nr2tSI8z310m7R4JDYgZc6J1PEZO3XZQ8l1kuGoqlAppBZuOYmPEqaHcVQQ== - dependencies: - bl "^5.0.0" - cids "^1.1.5" - err-code "^3.0.1" - hamt-sharding "^2.0.0" - ipfs-unixfs "^4.0.3" - ipld-dag-pb "^0.22.2" - it-all "^1.0.5" - it-batch "^1.0.8" - it-first "^1.0.6" - it-parallel-batch "^1.0.9" - merge-options "^3.0.4" - multihashing-async "^2.1.0" - rabin-wasm "^0.1.4" - uint8arrays "^2.1.2" - -ipfs-unixfs@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/ipfs-unixfs/-/ipfs-unixfs-4.0.3.tgz#7c43e5726052ade4317245358ac541ef3d63d94e" - integrity sha512-hzJ3X4vlKT8FQ3Xc4M1szaFVjsc1ZydN+E4VQ91aXxfpjFn9G2wsMo1EFdAXNq/BUnN5dgqIOMP5zRYr3DTsAw== - dependencies: - err-code "^3.0.1" - protobufjs "^6.10.2" - -ipld-dag-pb@^0.22.2: - version "0.22.3" - resolved "https://registry.yarnpkg.com/ipld-dag-pb/-/ipld-dag-pb-0.22.3.tgz#6d5af28b5752236a5cb0e0a1888c87dd733b55cd" - integrity sha512-dfG5C5OVAR4FEP7Al2CrHWvAyIM7UhAQrjnOYOIxXGQz5NlEj6wGX0XQf6Ru6or1na6upvV3NQfstapQG8X2rg== - dependencies: - cids "^1.0.0" - interface-ipld-format "^1.0.0" - multicodec "^3.0.1" - multihashing-async "^2.0.0" - protobufjs "^6.10.2" - stable "^0.1.8" - uint8arrays "^2.0.5" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-core-module@^2.13.0, is-core-module@^2.5.0: - version "2.14.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" - integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== - dependencies: - hasown "^2.0.2" - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -it-all@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/it-all/-/it-all-1.0.6.tgz#852557355367606295c4c3b7eff0136f07749335" - integrity sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A== - -it-batch@^1.0.8, it-batch@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/it-batch/-/it-batch-1.0.9.tgz#7e95aaacb3f9b1b8ca6c8b8367892171d6a5b37f" - integrity sha512-7Q7HXewMhNFltTsAMdSz6luNhyhkhEtGGbYek/8Xb/GiqYMtwUmopE1ocPSiJKKp3rM4Dt045sNFoUu+KZGNyA== - -it-first@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/it-first/-/it-first-1.0.7.tgz#a4bef40da8be21667f7d23e44dae652f5ccd7ab1" - integrity sha512-nvJKZoBpZD/6Rtde6FXqwDqDZGF1sCADmr2Zoc0hZsIvnE449gRFnGctxDf09Bzc/FWnHXAdaHVIetY6lrE0/g== - -it-parallel-batch@^1.0.9: - version "1.0.11" - resolved "https://registry.yarnpkg.com/it-parallel-batch/-/it-parallel-batch-1.0.11.tgz#f889b4e1c7a62ef24111dbafbaaa010b33d00f69" - integrity sha512-UWsWHv/kqBpMRmyZJzlmZeoAMA0F3SZr08FBdbhtbe+MtoEBgr/ZUAKrnenhXCBrsopy76QjRH2K/V8kNdupbQ== - dependencies: - it-batch "^1.0.9" - -js-sha3@0.8.0, js-sha3@^0.8.0: +js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-stringify-deterministic@^1.0.8: - version "1.0.12" - resolved "https://registry.yarnpkg.com/json-stringify-deterministic/-/json-stringify-deterministic-1.0.12.tgz#aaa3f907466ed01e3afd77b898d0a2b3b132820a" - integrity sha512-q3PN0lbUdv0pmurkBNdJH3pfFvOTL/Zp0lquqpvcjfKzt6Y0j49EPHAmVHCAS4Ceq/Y+PejWTzyiVpoY71+D6g== - just-performance@4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/just-performance/-/just-performance-4.3.0.tgz#cc2bc8c9227f09e97b6b1df4cd0de2df7ae16db1" integrity sha512-L7RjvtJsL0QO8xFs5wEoDDzzJwoiowRw6Rn/GnvldlchS2JQr9wFYPiwZcDfrbbujEKqKN0tvENdbjXdYhDp5Q== -kind-of@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - limiter@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/limiter/-/limiter-2.1.0.tgz#d38d7c5b63729bb84fb0c4d8594b7e955a5182a2" @@ -884,70 +442,11 @@ limiter@^2.1.0: dependencies: just-performance "4.3.0" -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -long@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" - integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -map-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== - -map-obj@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" - integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== - -meow@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" - integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== - dependencies: - "@types/minimist" "^1.2.0" - camelcase-keys "^6.2.2" - decamelize "^1.2.0" - decamelize-keys "^1.1.0" - hard-rejection "^2.1.0" - minimist-options "4.1.0" - normalize-package-data "^3.0.0" - read-pkg-up "^7.0.1" - redent "^3.0.0" - trim-newlines "^3.0.0" - type-fest "^0.18.0" - yargs-parser "^20.2.3" - -merge-options@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7" - integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== - dependencies: - is-plain-obj "^2.1.0" - mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -960,11 +459,6 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" -min-indent@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" - integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== - minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -975,71 +469,6 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimist-options@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" - integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== - dependencies: - arrify "^1.0.1" - is-plain-obj "^1.1.0" - kind-of "^6.0.3" - -minimist@^1.2.5: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -multibase@^4.0.1: - version "4.0.6" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.6.tgz#6e624341483d6123ca1ede956208cb821b440559" - integrity sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ== - dependencies: - "@multiformats/base-x" "^4.0.1" - -multicodec@^3.0.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-3.2.1.tgz#82de3254a0fb163a107c1aab324f2a91ef51efb2" - integrity sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw== - dependencies: - uint8arrays "^3.0.0" - varint "^6.0.0" - -multiformats@^9.4.2, multiformats@^9.6.4: - version "9.9.0" - resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" - integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== - -multihashes@^4.0.1, multihashes@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-4.0.3.tgz#426610539cd2551edbf533adeac4c06b3b90fb05" - integrity sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA== - dependencies: - multibase "^4.0.1" - uint8arrays "^3.0.0" - varint "^5.0.2" - -multihashing-async@^2.0.0, multihashing-async@^2.1.0: - version "2.1.4" - resolved "https://registry.yarnpkg.com/multihashing-async/-/multihashing-async-2.1.4.tgz#26dce2ec7a40f0e7f9e732fc23ca5f564d693843" - integrity sha512-sB1MiQXPSBTNRVSJc2zM157PXgDtud2nMFUEIvBrsq5Wv96sUclMRK/ecjoP1T/W61UJBqt4tCTwMkUpt2Gbzg== - dependencies: - blakejs "^1.1.0" - err-code "^3.0.0" - js-sha3 "^0.8.0" - multihashes "^4.0.1" - murmurhash3js-revisited "^3.0.0" - uint8arrays "^3.0.0" - -murmurhash3js-revisited@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz#6bd36e25de8f73394222adc6e41fa3fac08a5869" - integrity sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g== - node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -1047,255 +476,11 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^2.6.1: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - -normalize-package-data@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-package-data@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" - integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== - dependencies: - hosted-git-info "^4.0.1" - is-core-module "^2.5.0" - semver "^7.3.4" - validate-npm-package-license "^3.0.1" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -picocolors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== - -protobufjs@^6.10.2: - version "6.11.4" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" - integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== - dependencies: - "@protobufjs/aspromise" "^1.1.2" - "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" - "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" - "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" - "@protobufjs/path" "^1.1.2" - "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" - "@types/long" "^4.0.1" - "@types/node" ">=13.7.0" - long "^4.0.0" - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -quick-lru@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" - integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== - -rabin-wasm@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/rabin-wasm/-/rabin-wasm-0.1.5.tgz#5b625ca007d6a2cbc1456c78ae71d550addbc9c9" - integrity sha512-uWgQTo7pim1Rnj5TuWcCewRDTf0PEFTSlaUjWP4eY9EbLV9em08v89oCz/WO+wRxpYuO36XEHp4wgYQnAgOHzA== - dependencies: - "@assemblyscript/loader" "^0.9.4" - bl "^5.0.0" - debug "^4.3.1" - minimist "^1.2.5" - node-fetch "^2.6.1" - readable-stream "^3.6.0" - -read-pkg-up@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== - dependencies: - find-up "^4.1.0" - read-pkg "^5.2.0" - type-fest "^0.8.1" - -read-pkg@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== - dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^5.0.0" - type-fest "^0.6.0" - -readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -redent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" - integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== - dependencies: - indent-string "^4.0.0" - strip-indent "^3.0.0" - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -resolve@^1.10.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"semver@2 || 3 || 4 || 5": - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^7.3.4: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - -sparse-array@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/sparse-array/-/sparse-array-1.3.2.tgz#0e1a8b71706d356bc916fe754ff496d450ec20b0" - integrity sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg== - -spdx-correct@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" - integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.18" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" - integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -strip-indent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" - integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== - dependencies: - min-indent "^1.0.0" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -trim-newlines@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" - integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== - ts-node@^10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -1315,75 +500,11 @@ ts-node@^10.9.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -type-fest@^0.18.0: - version "0.18.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" - integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== - -type-fest@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -uint8arrays@^2.0.5, uint8arrays@^2.1.2: - version "2.1.10" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a" - integrity sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A== - dependencies: - multiformats "^9.4.2" - -uint8arrays@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" - integrity sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg== - dependencies: - multiformats "^9.4.2" - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -uri-js@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -varint@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" - integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== - -varint@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" - integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg== - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -1397,16 +518,6 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^20.2.3: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" diff --git a/examples/vanilla/src/index.ts b/examples/vanilla/src/index.ts index aa9e69a7..2fad2e5e 100644 --- a/examples/vanilla/src/index.ts +++ b/examples/vanilla/src/index.ts @@ -3,17 +3,14 @@ import { OrderBookApi, SubgraphApi, SupportedChainId } from '@cowprotocol/cow-sd // See more examples in /examples/cra ;(async function () { const orderBookApi = new OrderBookApi({ chainId: SupportedChainId.MAINNET }) - const subgraphApi = new SubgraphApi({ chainId: SupportedChainId.MAINNET }) const order = await orderBookApi.getOrder( '0xff2e2e54d178997f173266817c1e9ed6fee1a1aae4b43971c53b543cffcc2969845c6f5599fbb25dbdd1b9b013daf85c03f3c63763e4bc4a' ) - const lastDaysVolume = await subgraphApi.getTotals() - const orderElement = document.createElement('textarea') - orderElement.value = JSON.stringify({ order, lastDaysVolume }, null, 4) + orderElement.value = JSON.stringify({ order }, null, 4) orderElement.style.minWidth = '950px' orderElement.style.minHeight = '800px' diff --git a/package.json b/package.json index 83fbebc3..a9e120a0 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "types": "dist/index.d.ts", "scripts": { - "prebuild": "rm -rf dist && yarn run codegen", + "prebuild": "rm -rf dist", "build": "microbundle -f modern,esm,cjs", "start": "microbundle -f modern,esm,cjs watch", "postbuild": "cp package.json dist && cp README.md dist", @@ -31,6 +31,7 @@ "typechain:codegen": "typechain --target ethers-v5 --out-dir ./src/composable/generated './abi/*.json'" }, "dependencies": { + "@cowprotocol/app-data": "^2.1.0", "@cowprotocol/contracts": "^1.6.0", "@ethersproject/abstract-signer": "^5.7.0", "@openzeppelin/merkle-tree": "^1.0.5", diff --git a/src/index.ts b/src/index.ts index 07193af7..c049afd3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,3 +3,4 @@ export * from './order-book' export * from './subgraph' export * from './order-signing' export * from './composable' +export * from './trading' diff --git a/examples/nodejs/src/appDataUtils.ts b/src/trading/appDataUtils.ts similarity index 100% rename from examples/nodejs/src/appDataUtils.ts rename to src/trading/appDataUtils.ts diff --git a/examples/nodejs/src/consts.ts b/src/trading/consts.ts similarity index 80% rename from examples/nodejs/src/consts.ts rename to src/trading/consts.ts index 693f79f9..ec3072b6 100644 --- a/examples/nodejs/src/consts.ts +++ b/src/trading/consts.ts @@ -1,4 +1,4 @@ -import { EcdsaSigningScheme, SigningScheme } from '../../../src' +import { EcdsaSigningScheme, SigningScheme } from '../order-book' export const log = (text: string) => console.log(`[SDK] ${text}`) diff --git a/src/trading/index.ts b/src/trading/index.ts new file mode 100644 index 00000000..7404c257 --- /dev/null +++ b/src/trading/index.ts @@ -0,0 +1,2 @@ +export { postSwapOrder } from './postSwapOrder' +export { postLimitOrder } from './postLimitOrder' diff --git a/examples/nodejs/src/postLimitOrder.ts b/src/trading/postLimitOrder.ts similarity index 96% rename from examples/nodejs/src/postLimitOrder.ts rename to src/trading/postLimitOrder.ts index 0f277418..f4370dac 100644 --- a/examples/nodejs/src/postLimitOrder.ts +++ b/src/trading/postLimitOrder.ts @@ -1,7 +1,7 @@ import { LimitOrderAdvancedSettings, LimitOrderParameters } from './types' import { log } from './consts' import { ethers } from 'ethers' -import { OrderBookApi } from '../../../src' +import { OrderBookApi } from '../order-book' import { buildAppData } from './appDataUtils' import { postCoWProtocolTrade } from './postTrade' diff --git a/examples/nodejs/src/postSwapOrder.ts b/src/trading/postSwapOrder.ts similarity index 98% rename from examples/nodejs/src/postSwapOrder.ts rename to src/trading/postSwapOrder.ts index 1cf308e1..ae4e5ec0 100644 --- a/examples/nodejs/src/postSwapOrder.ts +++ b/src/trading/postSwapOrder.ts @@ -8,7 +8,7 @@ import { OrderQuoteSideKindSell, PriceQuality, SigningScheme, -} from '../../../src' +} from '../order-book' import { buildAppData } from './appDataUtils' import { postCoWProtocolTrade } from './postTrade' diff --git a/examples/nodejs/src/postTrade.ts b/src/trading/postTrade.ts similarity index 93% rename from examples/nodejs/src/postTrade.ts rename to src/trading/postTrade.ts index ea60d20b..68344f37 100644 --- a/examples/nodejs/src/postTrade.ts +++ b/src/trading/postTrade.ts @@ -1,13 +1,8 @@ -import { - getQuoteAmountsAndCosts, - OrderBookApi, - OrderCreation, - OrderSigningUtils, - type UnsignedOrder, -} from '../../../src' +import { getQuoteAmountsAndCosts, OrderBookApi, OrderCreation } from '../order-book' import { ethers } from 'ethers' import { AppDataInfo, LimitOrderParameters } from './types' import { DEFAULT_QUOTE_VALIDITY, log, SIGN_SCHEME_MAP } from './consts' +import { OrderSigningUtils, UnsignedOrder } from '../order-signing' export async function postCoWProtocolTrade( orderBookApi: OrderBookApi, diff --git a/examples/nodejs/src/types.ts b/src/trading/types.ts similarity index 92% rename from examples/nodejs/src/types.ts rename to src/trading/types.ts index f93eb5d9..71e384f8 100644 --- a/examples/nodejs/src/types.ts +++ b/src/trading/types.ts @@ -1,6 +1,7 @@ import { latest, LatestAppDataDocVersion, AppDataParams } from '@cowprotocol/app-data' -import { Address, SupportedChainId, CowEnv, OrderQuoteRequest, OrderKind } from '../../../src' +import { Address, OrderQuoteRequest, OrderKind } from '../order-book' import type { Signer } from '@ethersproject/abstract-signer' +import { CowEnv, SupportedChainId } from '../common' export interface TradeBaseParameters { kind: OrderKind diff --git a/yarn.lock b/yarn.lock index db9d8159..daa5d44f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -50,6 +50,11 @@ dependencies: node-fetch "^2.6.1" +"@assemblyscript/loader@^0.9.4": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.9.4.tgz#a483c54c1253656bb33babd464e3154a173e1577" + integrity sha512-HazVq9zwTVwGmqdwYzu7WyQ6FQVZ7SwET0KKQuKm55jD0IfUpZgN0OPIiZG3zV1iSrVYcN0bdwLRXI/VNCYsUA== + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" @@ -1761,6 +1766,17 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@cowprotocol/app-data@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@cowprotocol/app-data/-/app-data-2.1.0.tgz#55c95e7ffd3fb0dcfecd0fc64a4273955d1d63d1" + integrity sha512-gOlQxng7X5/aQoz2Eg27OegyKgpZVhOEdUQ9cUsc4OnSPal8F4tmLqefKQQWm4Ktaolk7zzh0kiL1vhWxvszmQ== + dependencies: + ajv "^8.11.0" + cross-fetch "^3.1.5" + ipfs-only-hash "^4.0.0" + json-stringify-deterministic "^1.0.8" + multiformats "^9.6.4" + "@cowprotocol/contracts@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@cowprotocol/contracts/-/contracts-1.6.0.tgz#d0fc83ed8c624b968d1a68bb5c74712c11ec81e0" @@ -2878,6 +2894,11 @@ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== +"@multiformats/base-x@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" + integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== + "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" @@ -2944,6 +2965,59 @@ tslib "^2.5.0" webcrypto-core "^1.7.7" +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + "@repeaterjs/repeater@3.0.4", "@repeaterjs/repeater@^3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca" @@ -3194,16 +3268,38 @@ resolved "https://registry.yarnpkg.com/@types/json-stable-stringify/-/json-stable-stringify-1.0.34.tgz#c0fb25e4d957e0ee2e497c1f553d7f8bb668fd75" integrity sha512-s2cfwagOQAS8o06TcwKfr9Wx11dNGbH2E9vJz1cqV+a/LOyhWNLUNd6JSRYNzvB4d29UuJX2M0Dj9vE1T8fRXw== +"@types/long@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + +"@types/minimist@^1.2.0": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" + integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== + "@types/node@*": version "18.6.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.1.tgz#828e4785ccca13f44e2fb6852ae0ef11e3e20ba5" integrity sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg== +"@types/node@>=13.7.0": + version "20.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420" + integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg== + dependencies: + undici-types "~5.26.4" + "@types/node@^18.13.0": version "18.13.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.13.0.tgz#0400d1e6ce87e9d3032c19eb6c58205b0d3f7850" integrity sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg== +"@types/normalize-package-data@^2.4.0": + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" + integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -3436,6 +3532,16 @@ ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.11.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.16.0.tgz#22e2a92b94f005f7e0f9c9d39652ef0b8f6f0cb4" + integrity sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw== + dependencies: + fast-deep-equal "^3.1.3" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.4.1" + ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -3525,6 +3631,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -3789,6 +3900,20 @@ bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" +bl@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273" + integrity sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ== + dependencies: + buffer "^6.0.3" + inherits "^2.0.4" + readable-stream "^3.4.0" + +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -3888,6 +4013,14 @@ buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + builtin-modules@^3.1.0: version "3.3.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" @@ -3926,6 +4059,15 @@ camel-case@^4.1.2: pascal-case "^3.1.2" tslib "^2.0.3" +camelcase-keys@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -4072,6 +4214,16 @@ ci-info@^3.2.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.2.tgz#6d2967ffa407466481c6c90b6e16b3098f080128" integrity sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg== +cids@^1.0.0, cids@^1.1.5, cids@^1.1.6: + version "1.1.9" + resolved "https://registry.yarnpkg.com/cids/-/cids-1.1.9.tgz#402c26db5c07059377bcd6fb82f2a24e7f2f4a4f" + integrity sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg== + dependencies: + multibase "^4.0.1" + multicodec "^3.0.1" + multihashes "^4.0.1" + uint8arrays "^3.0.0" + cjs-module-lexer@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" @@ -4443,7 +4595,15 @@ debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "2.1.2" -decamelize@^1.2.0: +decamelize-keys@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" + integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== @@ -4661,6 +4821,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +err-code@^3.0.0, err-code@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-3.0.1.tgz#a444c7b992705f2b120ee320b09972eef331c920" + integrity sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -5291,6 +5456,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function.prototype.name@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" @@ -5532,6 +5702,14 @@ gzip-size@^6.0.0: dependencies: duplexer "^0.1.2" +hamt-sharding@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hamt-sharding/-/hamt-sharding-2.0.1.tgz#f45686d0339e74b03b233bee1bde9587727129b6" + integrity sha512-vnjrmdXG9dDs1m/H4iJ6z0JFI2NtgsW5keRkTcM85NGak69Mkf5PHUqBz+Xs0T4sg0ppvj9O5EGAJo40FTxmmA== + dependencies: + sparse-array "^1.3.1" + uint8arrays "^3.0.0" + handlebars@^4.7.7: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" @@ -5557,6 +5735,11 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +hard-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -5618,6 +5801,13 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + header-case@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063" @@ -5635,6 +5825,18 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +hosted-git-info@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== + dependencies: + lru-cache "^6.0.0" + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -5687,7 +5889,7 @@ icss-utils@^5.0.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ieee754@^1.1.13: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -5781,6 +5983,15 @@ inquirer@^8.0.0: through "^2.3.6" wrap-ansi "^6.0.1" +interface-ipld-format@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/interface-ipld-format/-/interface-ipld-format-1.0.1.tgz#bee39c70c584a033e186ff057a2be89f215963e3" + integrity sha512-WV/ar+KQJVoQpqRDYdo7YPGYIUHJxCuOEhdvsRpzLqoOIVCqPKdMMYmsLL1nCRsF3yYNio+PAJbCKiv6drrEAg== + dependencies: + cids "^1.1.6" + multicodec "^3.0.1" + multihashes "^4.0.2" + internal-slot@^1.0.3, internal-slot@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" @@ -5797,6 +6008,55 @@ invariant@^2.2.4: dependencies: loose-envify "^1.0.0" +ipfs-only-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ipfs-only-hash/-/ipfs-only-hash-4.0.0.tgz#b3bd60a244d9eb7394961aa9d812a2e5ac7c04d6" + integrity sha512-TE1DZCvfw8i3gcsTq3P4TFx3cKFJ3sluu/J3XINkJhIN9OwJgNMqKA+WnKx6ByCb1IoPXsTp1KM7tupElb6SyA== + dependencies: + ipfs-unixfs-importer "^7.0.1" + meow "^9.0.0" + +ipfs-unixfs-importer@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ipfs-unixfs-importer/-/ipfs-unixfs-importer-7.0.3.tgz#b850e831ca9647d589ef50bc33421f65bab7bba6" + integrity sha512-qeFOlD3AQtGzr90sr5Tq1Bi8pT5Nr2tSI8z310m7R4JDYgZc6J1PEZO3XZQ8l1kuGoqlAppBZuOYmPEqaHcVQQ== + dependencies: + bl "^5.0.0" + cids "^1.1.5" + err-code "^3.0.1" + hamt-sharding "^2.0.0" + ipfs-unixfs "^4.0.3" + ipld-dag-pb "^0.22.2" + it-all "^1.0.5" + it-batch "^1.0.8" + it-first "^1.0.6" + it-parallel-batch "^1.0.9" + merge-options "^3.0.4" + multihashing-async "^2.1.0" + rabin-wasm "^0.1.4" + uint8arrays "^2.1.2" + +ipfs-unixfs@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/ipfs-unixfs/-/ipfs-unixfs-4.0.3.tgz#7c43e5726052ade4317245358ac541ef3d63d94e" + integrity sha512-hzJ3X4vlKT8FQ3Xc4M1szaFVjsc1ZydN+E4VQ91aXxfpjFn9G2wsMo1EFdAXNq/BUnN5dgqIOMP5zRYr3DTsAw== + dependencies: + err-code "^3.0.1" + protobufjs "^6.10.2" + +ipld-dag-pb@^0.22.2: + version "0.22.3" + resolved "https://registry.yarnpkg.com/ipld-dag-pb/-/ipld-dag-pb-0.22.3.tgz#6d5af28b5752236a5cb0e0a1888c87dd733b55cd" + integrity sha512-dfG5C5OVAR4FEP7Al2CrHWvAyIM7UhAQrjnOYOIxXGQz5NlEj6wGX0XQf6Ru6or1na6upvV3NQfstapQG8X2rg== + dependencies: + cids "^1.0.0" + interface-ipld-format "^1.0.0" + multicodec "^3.0.1" + multihashing-async "^2.0.0" + protobufjs "^6.10.2" + stable "^0.1.8" + uint8arrays "^2.0.5" + is-absolute@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" @@ -5846,6 +6106,13 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== +is-core-module@^2.13.0, is-core-module@^2.5.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" + integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== + dependencies: + hasown "^2.0.2" + is-core-module@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" @@ -5926,6 +6193,16 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-reference@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" @@ -6096,6 +6373,28 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +it-all@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/it-all/-/it-all-1.0.6.tgz#852557355367606295c4c3b7eff0136f07749335" + integrity sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A== + +it-batch@^1.0.8, it-batch@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/it-batch/-/it-batch-1.0.9.tgz#7e95aaacb3f9b1b8ca6c8b8367892171d6a5b37f" + integrity sha512-7Q7HXewMhNFltTsAMdSz6luNhyhkhEtGGbYek/8Xb/GiqYMtwUmopE1ocPSiJKKp3rM4Dt045sNFoUu+KZGNyA== + +it-first@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/it-first/-/it-first-1.0.7.tgz#a4bef40da8be21667f7d23e44dae652f5ccd7ab1" + integrity sha512-nvJKZoBpZD/6Rtde6FXqwDqDZGF1sCADmr2Zoc0hZsIvnE449gRFnGctxDf09Bzc/FWnHXAdaHVIetY6lrE0/g== + +it-parallel-batch@^1.0.9: + version "1.0.11" + resolved "https://registry.yarnpkg.com/it-parallel-batch/-/it-parallel-batch-1.0.11.tgz#f889b4e1c7a62ef24111dbafbaaa010b33d00f69" + integrity sha512-UWsWHv/kqBpMRmyZJzlmZeoAMA0F3SZr08FBdbhtbe+MtoEBgr/ZUAKrnenhXCBrsopy76QjRH2K/V8kNdupbQ== + dependencies: + it-batch "^1.0.9" + jake@^10.8.5: version "10.8.5" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46" @@ -6606,6 +6905,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-schema@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" @@ -6623,6 +6927,11 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "^0.0.1" +json-stringify-deterministic@^1.0.8: + version "1.0.12" + resolved "https://registry.yarnpkg.com/json-stringify-deterministic/-/json-stringify-deterministic-1.0.12.tgz#aaa3f907466ed01e3afd77b898d0a2b3b132820a" + integrity sha512-q3PN0lbUdv0pmurkBNdJH3pfFvOTL/Zp0lquqpvcjfKzt6Y0j49EPHAmVHCAS4Ceq/Y+PejWTzyiVpoY71+D6g== + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -6682,6 +6991,11 @@ just-performance@4.3.0: resolved "https://registry.yarnpkg.com/just-performance/-/just-performance-4.3.0.tgz#cc2bc8c9227f09e97b6b1df4cd0de2df7ae16db1" integrity sha512-L7RjvtJsL0QO8xFs5wEoDDzzJwoiowRw6Rn/GnvldlchS2JQr9wFYPiwZcDfrbbujEKqKN0tvENdbjXdYhDp5Q== +kind-of@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -6813,6 +7127,11 @@ log-update@^4.0.0: slice-ansi "^4.0.0" wrap-ansi "^6.2.0" +long@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + loose-envify@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -6879,6 +7198,16 @@ map-cache@^0.2.0: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== + +map-obj@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== + map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" @@ -6899,6 +7228,31 @@ mdn-data@2.0.14: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== +meow@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize "^1.2.0" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -6987,6 +7341,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -7018,6 +7377,15 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimist-options@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" + integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + kind-of "^6.0.3" + minimist@^1.2.5: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" @@ -7038,6 +7406,52 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +multibase@^4.0.1: + version "4.0.6" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.6.tgz#6e624341483d6123ca1ede956208cb821b440559" + integrity sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ== + dependencies: + "@multiformats/base-x" "^4.0.1" + +multicodec@^3.0.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-3.2.1.tgz#82de3254a0fb163a107c1aab324f2a91ef51efb2" + integrity sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw== + dependencies: + uint8arrays "^3.0.0" + varint "^6.0.0" + +multiformats@^9.4.2, multiformats@^9.6.4: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== + +multihashes@^4.0.1, multihashes@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-4.0.3.tgz#426610539cd2551edbf533adeac4c06b3b90fb05" + integrity sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA== + dependencies: + multibase "^4.0.1" + uint8arrays "^3.0.0" + varint "^5.0.2" + +multihashing-async@^2.0.0, multihashing-async@^2.1.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/multihashing-async/-/multihashing-async-2.1.4.tgz#26dce2ec7a40f0e7f9e732fc23ca5f564d693843" + integrity sha512-sB1MiQXPSBTNRVSJc2zM157PXgDtud2nMFUEIvBrsq5Wv96sUclMRK/ecjoP1T/W61UJBqt4tCTwMkUpt2Gbzg== + dependencies: + blakejs "^1.1.0" + err-code "^3.0.0" + js-sha3 "^0.8.0" + multihashes "^4.0.1" + murmurhash3js-revisited "^3.0.0" + uint8arrays "^3.0.0" + +murmurhash3js-revisited@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz#6bd36e25de8f73394222adc6e41fa3fac08a5869" + integrity sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g== + mute-stream@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -7110,6 +7524,26 @@ node-releases@^2.0.8: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-package-data@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" + integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== + dependencies: + hosted-git-info "^4.0.1" + is-core-module "^2.5.0" + semver "^7.3.4" + validate-npm-package-license "^3.0.1" + normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -7789,6 +8223,25 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" +protobufjs@^6.10.2: + version "6.11.4" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" + integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" ">=13.7.0" + long "^4.0.0" + ps-tree@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" @@ -7838,6 +8291,23 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== + +rabin-wasm@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/rabin-wasm/-/rabin-wasm-0.1.5.tgz#5b625ca007d6a2cbc1456c78ae71d550addbc9c9" + integrity sha512-uWgQTo7pim1Rnj5TuWcCewRDTf0PEFTSlaUjWP4eY9EbLV9em08v89oCz/WO+wRxpYuO36XEHp4wgYQnAgOHzA== + dependencies: + "@assemblyscript/loader" "^0.9.4" + bl "^5.0.0" + debug "^4.3.1" + minimist "^1.2.5" + node-fetch "^2.6.1" + readable-stream "^3.6.0" + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -7850,7 +8320,26 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -readable-stream@^3.4.0: +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -7866,6 +8355,14 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + reduce-flatten@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" @@ -7988,6 +8485,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -8022,6 +8524,15 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.0.tgz#c1a0028c2d166ec2fbf7d0644584927e76e7400e" integrity sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg== +resolve@^1.10.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" @@ -8193,6 +8704,11 @@ scuid@^1.1.0: resolved "https://registry.yarnpkg.com/scuid/-/scuid-1.1.0.tgz#d3f9f920956e737a60f72d0e4ad280bf324d5dab" integrity sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg== +"semver@2 || 3 || 4 || 5": + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -8203,6 +8719,11 @@ semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +semver@^7.3.4: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + semver@^7.3.7: version "7.3.7" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" @@ -8351,6 +8872,37 @@ sourcemap-codec@^1.4.8: resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== +sparse-array@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/sparse-array/-/sparse-array-1.3.2.tgz#0e1a8b71706d356bc916fe754ff496d450ec20b0" + integrity sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg== + +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.18" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" + integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== + split@0.3: version "0.3.3" resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" @@ -8509,6 +9061,13 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -8669,6 +9228,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +trim-newlines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" + integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== + ts-command-line-args@^2.2.0: version "2.5.1" resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" @@ -8781,6 +9345,11 @@ type-detect@4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" + integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -8791,6 +9360,16 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + typechain@^8.2.0: version "8.3.1" resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.3.1.tgz#dccbc839b94877997536c356380eff7325395cfb" @@ -8841,6 +9420,20 @@ uglify-js@^3.1.4: resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== +uint8arrays@^2.0.5, uint8arrays@^2.1.2: + version "2.1.10" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a" + integrity sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A== + dependencies: + multiformats "^9.4.2" + +uint8arrays@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" + integrity sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg== + dependencies: + multiformats "^9.4.2" + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -8856,6 +9449,11 @@ unc-path-regex@^0.1.2: resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" integrity sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" @@ -8934,7 +9532,7 @@ upper-case@^2.0.2: dependencies: tslib "^2.0.3" -uri-js@^4.2.2: +uri-js@^4.2.2, uri-js@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== @@ -8977,11 +9575,29 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + value-or-promise@^1.0.11, value-or-promise@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.12.tgz#0e5abfeec70148c78460a849f6b003ea7986f15c" integrity sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q== +varint@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== + +varint@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" + integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg== + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -9173,6 +9789,11 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.3: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" From ee092bbcc8c2643e007c46da0b0bce12637156ec Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 27 Jun 2024 20:02:40 +0500 Subject: [PATCH 04/67] feat: js example for trade-sdk --- examples/vanilla/package.json | 6 +- examples/vanilla/src/formState.ts | 50 +++ examples/vanilla/src/index.ts | 88 ++++- examples/vanilla/src/pageActions.ts | 96 ++++++ examples/vanilla/src/pageHtml.ts | 81 +++++ examples/vanilla/src/styles.css | 41 +++ examples/vanilla/src/tokens.ts | 50 +++ examples/vanilla/src/utils.ts | 3 + examples/vanilla/tsconfig.json | 4 +- examples/vanilla/webpack.config.js | 10 + examples/vanilla/yarn.lock | 497 ++++++---------------------- src/composable/ConditionalOrder.ts | 5 +- src/order-signing/utils.ts | 2 +- src/trading/getOrderToSign.ts | 59 ++++ src/trading/getQuote.ts | 95 ++++++ src/trading/index.ts | 4 + src/trading/postLimitOrder.ts | 21 +- src/trading/postSwapOrder.ts | 85 +---- src/trading/postTrade.ts | 62 +--- src/trading/quoteUtils.ts | 23 ++ src/trading/types.ts | 2 + 21 files changed, 726 insertions(+), 558 deletions(-) create mode 100644 examples/vanilla/src/formState.ts create mode 100644 examples/vanilla/src/pageActions.ts create mode 100644 examples/vanilla/src/pageHtml.ts create mode 100644 examples/vanilla/src/styles.css create mode 100644 examples/vanilla/src/tokens.ts create mode 100644 examples/vanilla/src/utils.ts create mode 100644 src/trading/getOrderToSign.ts create mode 100644 src/trading/getQuote.ts create mode 100644 src/trading/quoteUtils.ts diff --git a/examples/vanilla/package.json b/examples/vanilla/package.json index 61e5b4a2..699c7253 100644 --- a/examples/vanilla/package.json +++ b/examples/vanilla/package.json @@ -7,13 +7,13 @@ "start": "webpack serve --mode=development", "test": "echo \"Error: no test specified\" && exit 1" }, - "dependencies": { - "@cowprotocol/cow-sdk": "^4.0.3" - }, + "dependencies": {}, "author": "", "license": "ISC", "devDependencies": { + "css-loader": "^7.1.2", "html-webpack-plugin": "^5.5.0", + "style-loader": "^4.0.0", "ts-loader": "^9.4.2", "webpack": "^5.76.3", "webpack-cli": "^5.0.1", diff --git a/examples/vanilla/src/formState.ts b/examples/vanilla/src/formState.ts new file mode 100644 index 00000000..5d9ab500 --- /dev/null +++ b/examples/vanilla/src/formState.ts @@ -0,0 +1,50 @@ +import { OrderKind, SupportedChainId, SwapParameters } from '../../../src' +import { TOKENS } from './tokens' + +const appCode = 'trade-sdk-example' + +interface FormState { + privateKey: string + chainId: string + sellToken: string + buyToken: string + amount: string + slippageBps: string + kind: 'sell' | 'buy' +} + +export const getFormState = (): FormState => { + return Object.fromEntries(new FormData(document.getElementById('form') as HTMLFormElement)) as unknown as FormState +} + +export const getSwapParameters = (): SwapParameters => { + const { + privateKey, + slippageBps: _slippageBps, + chainId: _chainId, + sellToken: _sellToken, + buyToken: _buyToken, + amount: _amount, + kind, + } = getFormState() + + const chainId: SupportedChainId = +_chainId + const isSell = kind === 'sell' + const sellToken = TOKENS[chainId].find((t) => t.address === _sellToken) + const buyToken = TOKENS[chainId].find((t) => t.address === _buyToken) + const amount = BigInt(_amount) * BigInt(10 ** (isSell ? sellToken.decimals : buyToken.decimals)) + const slippageBps = _slippageBps ? +_slippageBps : undefined + + return { + appCode, + signer: privateKey, + chainId, + sellToken: sellToken.address, + sellTokenDecimals: sellToken.decimals, + buyToken: buyToken.address, + buyTokenDecimals: buyToken.decimals, + amount: amount.toString(), + slippageBps, + kind: isSell ? OrderKind.SELL : OrderKind.BUY, + } +} diff --git a/examples/vanilla/src/index.ts b/examples/vanilla/src/index.ts index 2fad2e5e..e20bc74f 100644 --- a/examples/vanilla/src/index.ts +++ b/examples/vanilla/src/index.ts @@ -1,18 +1,84 @@ -import { OrderBookApi, SubgraphApi, SupportedChainId } from '@cowprotocol/cow-sdk' +import { SupportedChainId, getQuote, UnsignedOrder } from '../../../src' -// See more examples in /examples/cra +import { getOrderToSignFromQuoteResult, swapParamsToLimitOrderParams, postCoWProtocolTrade } from '../../../src/trading' + +import { TOKENS } from './tokens' +import { atomsToAmount } from './utils' +import { pageHtml } from './pageHtml' +import { pageActions, printResult } from './pageActions' +import { GetQuoteResult } from '../../../src/trading/getQuote' +import { getFormState, getSwapParameters } from './formState' +import './styles.css' + +// Run the example ;(async function () { - const orderBookApi = new OrderBookApi({ chainId: SupportedChainId.MAINNET }) + let getQuoteResult: GetQuoteResult | null = null + + // Render page + const page = pageHtml() + document.body.appendChild(page) + + // Bind actions to the page + pageActions({ + onFormReset() { + getQuoteResult = null + }, + async onGetQuote() { + const { + slippageBps: _slippageBps, + chainId: _chainId, + sellToken: _sellToken, + buyToken: _buyToken, + amount: _amount, + kind, + } = getFormState() + + const chainId: SupportedChainId = +_chainId + const isSell = kind === 'sell' + const sellToken = TOKENS[chainId].find((t) => t.address === _sellToken) + const buyToken = TOKENS[chainId].find((t) => t.address === _buyToken) + + getQuoteResult = await getQuote(getSwapParameters()) + + const { + amountsAndCosts: { beforeNetworkCosts, afterSlippage }, + } = getQuoteResult + + console.log('Quote results:', getQuoteResult) + + const outputToken = isSell ? buyToken : sellToken - const order = await orderBookApi.getOrder( - '0xff2e2e54d178997f173266817c1e9ed6fee1a1aae4b43971c53b543cffcc2969845c6f5599fbb25dbdd1b9b013daf85c03f3c63763e4bc4a' - ) + printResult(` + Quote amount: ${atomsToAmount( + beforeNetworkCosts[isSell ? 'buyAmount' : 'sellAmount'], + outputToken.decimals + )} ${outputToken.symbol} + Amount to sign: ${atomsToAmount( + afterSlippage[isSell ? 'buyAmount' : 'sellAmount'], + outputToken.decimals + )} ${outputToken.symbol} + See more info in the console (Quote results) + `) + }, + async onConfirmOrder() { + const orderToSign = await getOrderToSignFromQuoteResult(getQuoteResult, getSwapParameters()) - const orderElement = document.createElement('textarea') + printResult(` + You are going to sign: + ${JSON.stringify(orderToSign, null, 4)} + `) + }, + async onSignAndSendOrder() { + const { orderBookApi, signer, appDataInfo, quoteResponse } = getQuoteResult - orderElement.value = JSON.stringify({ order }, null, 4) - orderElement.style.minWidth = '950px' - orderElement.style.minHeight = '800px' + const orderId = await postCoWProtocolTrade( + orderBookApi, + signer, + appDataInfo, + swapParamsToLimitOrderParams(getSwapParameters(), quoteResponse) + ) - document.body.appendChild(orderElement) + printResult(`Order created, id: ${orderId}`) + }, + }) })() diff --git a/examples/vanilla/src/pageActions.ts b/examples/vanilla/src/pageActions.ts new file mode 100644 index 00000000..4329ffc2 --- /dev/null +++ b/examples/vanilla/src/pageActions.ts @@ -0,0 +1,96 @@ +import { tokensSelect } from './pageHtml' + +const sendOrderText = 'Send order' + +interface Actions { + onFormReset(): void + onGetQuote(): Promise + onConfirmOrder(): Promise + onSignAndSendOrder(): Promise +} + +export function pageActions(actions: Actions) { + onFormReset(actions.onFormReset) + onNetworkChange() + onGetQuote(actions) +} + +export function printResult(text: string) { + const resultsEl = document.getElementById('results')! as HTMLTextAreaElement + + resultsEl.value = text + .split('\n') + .map((t) => t.trim()) + .join('\n') +} + +function onFormReset(callback: () => void) { + document.getElementById('form')?.addEventListener('change', () => { + printResult('') + + document.getElementById('sendOrder').innerText = sendOrderText + callback() + }) +} + +function onNetworkChange() { + document.getElementById('chainId').addEventListener('change', (event) => { + const chainId = +(event.target as unknown as { value: string }).value + + document.getElementById('sellToken')!.parentElement.innerHTML = tokensSelect(chainId, 'sellToken') + document.getElementById('buyToken')!.parentElement.innerHTML = tokensSelect(chainId, 'buyToken') + }) +} + +function onGetQuote(actions: Actions) { + document.getElementById('getQuote').addEventListener('click', (event) => { + event.preventDefault() + + printResult('Loading...') + + const sendOrderEl = document.getElementById('sendOrder') + + sendOrderEl.innerText = sendOrderText + + actions.onFormReset() + + actions + .onGetQuote() + .then(() => { + const sendOrderEl = document.getElementById('sendOrder') as HTMLButtonElement + + sendOrderEl.style.display = 'inline-block' + + sendOrderEl.addEventListener('click', async (event) => { + event.preventDefault() + + sendOrderEl.disabled = true + sendOrderEl.innerText = 'Loading...' + + try { + if (sendOrderEl.innerText === sendOrderText) { + await actions.onConfirmOrder() + + sendOrderEl.innerText = 'Sign and send' + } else { + await actions.onSignAndSendOrder() + + sendOrderEl.innerText = sendOrderText + sendOrderEl.style.display = 'none' + } + } catch (error) { + printError(error) + } finally { + sendOrderEl.disabled = false + } + }) + }) + .catch((error) => { + printError(error) + }) + }) +} + +function printError(error: any) { + printResult(JSON.stringify(error.body || error.message || error.toString(), null, 4)) +} diff --git a/examples/vanilla/src/pageHtml.ts b/examples/vanilla/src/pageHtml.ts new file mode 100644 index 00000000..94d50db5 --- /dev/null +++ b/examples/vanilla/src/pageHtml.ts @@ -0,0 +1,81 @@ +import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from '../../../src' +import { TOKENS } from './tokens' + +const chainId = SupportedChainId.MAINNET + +export const tokensSelect = (chainId: SupportedChainId, name: string) => + `` + +export function pageHtml() { + const page = document.createElement('div') + + const networksSelect = () => + `` + + page.innerHTML = ` + + + + + +
+
+

Swap

+ +
+ +
+
+ +
+ +
${networksSelect()}
+
+ +
+ +
${tokensSelect(chainId, 'sellToken')}
+
+ +
+ +
${tokensSelect(chainId, 'buyToken')}
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ + +
+
+
+

Result:

+ +
+ ` + + return page +} diff --git a/examples/vanilla/src/styles.css b/examples/vanilla/src/styles.css new file mode 100644 index 00000000..3e6ccb54 --- /dev/null +++ b/examples/vanilla/src/styles.css @@ -0,0 +1,41 @@ +#layout { + margin: 0 auto; +} + +#layout td { + vertical-align: top; +} + +#form { + min-width: 400px; +} + +#form > div { + border: 1px solid #d4d9de; + margin: 10px; + padding: 10px; +} + +#form input, #form select { + width: 100%; + box-sizing: border-box; +} + +#form button { + background: #282c34; + color: #fff; + font-size: 18px; + padding: 5px 10px; + cursor: pointer; + border: 0; + border-radius: 4px; +} + +#results { + min-height: 400px; + min-width: 600px; +} + +#sendOrder { + display: none; +} diff --git a/examples/vanilla/src/tokens.ts b/examples/vanilla/src/tokens.ts new file mode 100644 index 00000000..75c0b6ad --- /dev/null +++ b/examples/vanilla/src/tokens.ts @@ -0,0 +1,50 @@ +import { SupportedChainId } from '../../../src' + +class Token { + constructor( + public readonly chainId: SupportedChainId, + public readonly address: string, + public readonly decimals: number, + public readonly symbol: string, + public readonly name: string + ) {} +} + +export const TOKENS: Record = { + [SupportedChainId.MAINNET]: [ + new Token(SupportedChainId.MAINNET, '0xdAC17F958D2ee523a2206206994597C13D831ec7', 6, 'USDT', 'Tether USD'), + new Token(SupportedChainId.MAINNET, '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 8, 'WBTC', 'Wrapped BTC'), + new Token(SupportedChainId.MAINNET, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD Coin'), + new Token(SupportedChainId.MAINNET, '0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB', 18, 'COW', 'CoW Protocol Token'), + ], + [SupportedChainId.GNOSIS_CHAIN]: [ + new Token(SupportedChainId.GNOSIS_CHAIN, '0x4ECaBa5870353805a9F068101A40E0f32ed605C6', 6, 'USDT', 'Tether USD'), + new Token(SupportedChainId.GNOSIS_CHAIN, '0x8e5bbbb09ed1ebde8674cda39a0c169401db4252', 8, 'WBTC', 'Wrapped BTC'), + new Token(SupportedChainId.GNOSIS_CHAIN, '0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83', 6, 'USDC', 'USD Coin'), + new Token( + SupportedChainId.GNOSIS_CHAIN, + '0x177127622c4A00F3d409B75571e12cB3c8973d3c', + 18, + 'COW', + 'CoW Protocol Token' + ), + ], + [SupportedChainId.ARBITRUM_ONE]: [ + new Token(SupportedChainId.ARBITRUM_ONE, '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', 6, 'USDT', 'Tether USD'), + new Token(SupportedChainId.ARBITRUM_ONE, '0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f', 8, 'WBTC', 'Wrapped BTC'), + new Token(SupportedChainId.ARBITRUM_ONE, '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', 6, 'USDC', 'USD Coin'), + new Token( + SupportedChainId.ARBITRUM_ONE, + '0xcb8b5cd20bdcaea9a010ac1f8d835824f5c87a04', + 18, + 'COW', + 'CoW Protocol Token' + ), + ], + [SupportedChainId.SEPOLIA]: [ + new Token(SupportedChainId.SEPOLIA, '0x58eb19ef91e8a6327fed391b51ae1887b833cc91', 6, 'USDT', 'Tether USD'), + new Token(SupportedChainId.SEPOLIA, '0xd3f3d46FeBCD4CdAa2B83799b7A5CdcB69d135De', 18, 'GNO', 'GNO (test)'), + new Token(SupportedChainId.SEPOLIA, '0xbe72E441BF55620febc26715db68d3494213D8Cb', 18, 'USDC', 'USDC (test)'), + new Token(SupportedChainId.SEPOLIA, '0x0625aFB445C3B6B7B929342a04A22599fd5dBB59', 18, 'COW', 'CoW Protocol Token'), + ], +} diff --git a/examples/vanilla/src/utils.ts b/examples/vanilla/src/utils.ts new file mode 100644 index 00000000..992372d0 --- /dev/null +++ b/examples/vanilla/src/utils.ts @@ -0,0 +1,3 @@ +export function atomsToAmount(value: bigint, decimals: number): string { + return (value / BigInt(10 ** decimals)).toString() +} diff --git a/examples/vanilla/tsconfig.json b/examples/vanilla/tsconfig.json index 207d4d4b..bf27f2fc 100644 --- a/examples/vanilla/tsconfig.json +++ b/examples/vanilla/tsconfig.json @@ -2,8 +2,8 @@ "compilerOptions": { "outDir": "./dist/", "noImplicitAny": true, - "module": "es6", - "target": "es5", + "module": "esnext", + "target": "esnext", "allowJs": true, "moduleResolution": "node" } diff --git a/examples/vanilla/webpack.config.js b/examples/vanilla/webpack.config.js index a84fe8c8..98e03dcc 100644 --- a/examples/vanilla/webpack.config.js +++ b/examples/vanilla/webpack.config.js @@ -9,11 +9,21 @@ module.exports = { }, module: { rules: [ + { + test: /\.css$/i, + use: ['style-loader', 'css-loader'], + }, { test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/, }, + { + test: /\.m?js$/, + resolve: { + fullySpecified: false, + }, + }, ], }, resolve: { diff --git a/examples/vanilla/yarn.lock b/examples/vanilla/yarn.lock index 93f507bf..3cdb7399 100644 --- a/examples/vanilla/yarn.lock +++ b/examples/vanilla/yarn.lock @@ -2,207 +2,11 @@ # yarn lockfile v1 -"@cowprotocol/contracts@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@cowprotocol/contracts/-/contracts-1.4.0.tgz#e93e5f25aac76feeaa348fa57231903274676247" - integrity sha512-XLs3SlPmXD4lbiWIO7mxxuCn1eE5isuO6EUlE1cj17HqN/wukDAN0xXYPx6umOH/XdjGS33miMiPHELEyY9siw== - -"@cowprotocol/cow-sdk@^4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@cowprotocol/cow-sdk/-/cow-sdk-4.0.3.tgz#bd4da3e1821c33e6f5a29e04786aaa16c346bb02" - integrity sha512-bEGpHwfFpUv4he5kH99gmmJU1kZaqRH4JUCeFqIzZAxey86i+qLzVS00r3GDw5o/tKYY/0677hgusH2srr8MZw== - dependencies: - "@cowprotocol/contracts" "^1.4.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@openzeppelin/merkle-tree" "^1.0.5" - cross-fetch "^3.1.5" - exponential-backoff "^3.1.1" - graphql "^16.3.0" - graphql-request "^4.3.0" - limiter "^2.1.0" - "@discoveryjs/json-ext@^0.5.0": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@ethersproject/abi@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" - integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/abstract-provider@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" - integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - -"@ethersproject/abstract-signer@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" - integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/address@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" - integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/base64@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" - integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/bignumber@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" - integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - bn.js "^5.2.1" - -"@ethersproject/bytes@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" - integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/constants@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/hash@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" - integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/keccak256@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" - integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - js-sha3 "0.8.0" - -"@ethersproject/logger@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" - integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== - -"@ethersproject/networks@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" - integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/properties@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" - integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" - integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/signing-key@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" - integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - bn.js "^5.2.1" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/strings@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" - integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/transactions@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" - integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/web@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" - integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@jridgewell/gen-mapping@^0.3.0": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" @@ -248,46 +52,6 @@ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== -"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" - integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== - -"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" - integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== - -"@openzeppelin/merkle-tree@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@openzeppelin/merkle-tree/-/merkle-tree-1.0.5.tgz#4836d377777a7e39f31674f06ec3d6909def7913" - integrity sha512-JkwG2ysdHeIphrScNxYagPy6jZeNONgDRyqU6lbFgE8HKCZFSkcP8r6AjZs+3HZk4uRNV0kNBBzuWhKQ3YV7Kw== - dependencies: - "@ethersproject/abi" "^5.7.0" - ethereum-cryptography "^1.1.2" - -"@scure/base@~1.1.0": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f" - integrity sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q== - -"@scure/bip32@1.1.5": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" - integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== - dependencies: - "@noble/hashes" "~1.2.0" - "@noble/secp256k1" "~1.7.0" - "@scure/base" "~1.1.0" - -"@scure/bip39@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" - integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== - dependencies: - "@noble/hashes" "~1.2.0" - "@scure/base" "~1.1.0" - "@types/body-parser@*": version "1.19.2" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" @@ -672,11 +436,6 @@ array-flatten@^2.1.2: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -692,16 +451,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - body-parser@1.20.1: version "1.20.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" @@ -750,11 +499,6 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - browserslist@^4.14.5: version "4.21.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" @@ -862,13 +606,6 @@ colorette@^2.0.10, colorette@^2.0.14: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -941,13 +678,6 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cross-fetch@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== - dependencies: - node-fetch "2.6.7" - cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -957,6 +687,20 @@ cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +css-loader@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-7.1.2.tgz#64671541c6efe06b0e22e750503106bdd86880f8" + integrity sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.33" + postcss-modules-extract-imports "^3.1.0" + postcss-modules-local-by-default "^4.0.5" + postcss-modules-scope "^3.2.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.5.4" + css-select@^4.1.3: version "4.3.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" @@ -973,6 +717,11 @@ css-what@^6.0.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -999,11 +748,6 @@ define-lazy-prop@^2.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -1091,19 +835,6 @@ electron-to-chromium@^1.4.284: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.341.tgz#ab31e9e57ef7758a14c7a7977a1978d599514470" integrity sha512-R4A8VfUBQY9WmAhuqY5tjHRf5fH2AAf6vqitBOE0y6u2PgHgqHSrhZmu78dIX3fVZtjqlwJNX1i2zwC3VpHtQQ== -elliptic@6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -1172,16 +903,6 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -ethereum-cryptography@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" - integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== - dependencies: - "@noble/hashes" "1.2.0" - "@noble/secp256k1" "1.7.1" - "@scure/bip32" "1.1.5" - "@scure/bip39" "1.1.1" - eventemitter3@^4.0.0: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -1207,11 +928,6 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -exponential-backoff@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" - integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== - express@^4.17.3: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" @@ -1249,11 +965,6 @@ express@^4.17.3: utils-merge "1.0.1" vary "~1.1.2" -extract-files@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" - integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1309,15 +1020,6 @@ follow-redirects@^1.0.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -1391,20 +1093,6 @@ graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -graphql-request@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-4.3.0.tgz#b934e08fcae764aa2cdc697d3c821f046cb5dbf2" - integrity sha512-2v6hQViJvSsifK606AliqiNiijb1uwWp6Re7o0RTyH+uRTv/u7Uqm2g4Fjq/LgZIzARB38RZEvVBFOQOVdlBow== - dependencies: - cross-fetch "^3.1.5" - extract-files "^9.0.0" - form-data "^3.0.0" - -graphql@^16.3.0: - version "16.6.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" - integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== - handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -1427,28 +1115,11 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" @@ -1561,6 +1232,11 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + import-local@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" @@ -1577,7 +1253,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1686,11 +1362,6 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" -js-sha3@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - json-parse-even-better-errors@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" @@ -1706,11 +1377,6 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -just-performance@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/just-performance/-/just-performance-4.3.0.tgz#cc2bc8c9227f09e97b6b1df4cd0de2df7ae16db1" - integrity sha512-L7RjvtJsL0QO8xFs5wEoDDzzJwoiowRw6Rn/GnvldlchS2JQr9wFYPiwZcDfrbbujEKqKN0tvENdbjXdYhDp5Q== - kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -1724,13 +1390,6 @@ launch-editor@^2.6.0: picocolors "^1.0.0" shell-quote "^1.7.3" -limiter@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/limiter/-/limiter-2.1.0.tgz#d38d7c5b63729bb84fb0c4d8594b7e955a5182a2" - integrity sha512-361TYz6iay6n+9KvUUImqdLuFigK+K79qrUtBsXhJTLdH4rIt/r1y8r1iozwh8KbZNpujbFTSh74mJ7bwbAMOw== - dependencies: - just-performance "4.3.0" - loader-runner@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" @@ -1802,7 +1461,7 @@ mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -1819,16 +1478,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: +minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -1859,6 +1513,11 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -1877,13 +1536,6 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" -node-fetch@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -2048,6 +1700,56 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +postcss-modules-extract-imports@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== + +postcss-modules-local-by-default@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" + integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" + integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.1.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53" + integrity sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.33: + version "8.4.38" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" + integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.0" + source-map-js "^1.2.0" + pretty-error@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" @@ -2251,6 +1953,11 @@ semver@^7.3.4: dependencies: lru-cache "^6.0.0" +semver@^7.5.4: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -2357,6 +2064,11 @@ sockjs@^0.3.24: uuid "^8.3.2" websocket-driver "^0.7.4" +source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -2429,6 +2141,11 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +style-loader@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-4.0.0.tgz#0ea96e468f43c69600011e0589cb05c44f3b17a5" + integrity sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA== + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -2491,11 +2208,6 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - ts-loader@^9.4.2: version "9.4.2" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.2.tgz#80a45eee92dd5170b900b3d00abcfa14949aeb78" @@ -2539,7 +2251,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -2579,11 +2291,6 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - webpack-cli@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.0.1.tgz#95fc0495ac4065e9423a722dec9175560b6f2d9a" @@ -2707,14 +2414,6 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" diff --git a/src/composable/ConditionalOrder.ts b/src/composable/ConditionalOrder.ts index fa1bc6f9..f322e636 100644 --- a/src/composable/ConditionalOrder.ts +++ b/src/composable/ConditionalOrder.ts @@ -6,6 +6,7 @@ import { ConditionalOrderArguments, ConditionalOrderParams, ContextFactory, + IsNotValid, IsValidResult, OwnerContext, PollParams, @@ -95,7 +96,7 @@ export abstract class ConditionalOrder { assertIsValid(): void { const isValidResult = this.isValid() if (!isValidResult.isValid) { - throw new Error(`Invalid order: ${isValidResult.reason}`) + throw new Error(`Invalid order: ${(isValidResult as IsNotValid).reason}`) } } @@ -256,7 +257,7 @@ export abstract class ConditionalOrder { if (!isValid.isValid) { return { result: PollResultCode.DONT_TRY_AGAIN, - reason: `InvalidConditionalOrder. Reason: ${isValid.reason}`, + reason: `InvalidConditionalOrder. Reason: ${(isValid as IsNotValid).reason}`, } } diff --git a/src/order-signing/utils.ts b/src/order-signing/utils.ts index 9c481fca..18f33fd6 100644 --- a/src/order-signing/utils.ts +++ b/src/order-signing/utils.ts @@ -60,7 +60,7 @@ async function _signOrder(params: SignOrderParams): Promise { const domain = getDomain(chainId) - return signOrderGp(domain, order as OrderFromContract, signer, mapSigningSchema[signingScheme]) + return signOrderGp(domain, order as unknown as OrderFromContract, signer, mapSigningSchema[signingScheme]) } async function _signOrderCancellation(params: SignOrderCancellationParams): Promise { diff --git a/src/trading/getOrderToSign.ts b/src/trading/getOrderToSign.ts new file mode 100644 index 00000000..3d20c86c --- /dev/null +++ b/src/trading/getOrderToSign.ts @@ -0,0 +1,59 @@ +import { getQuoteAmountsAndCosts, type OrderParameters } from '../order-book' +import { UnsignedOrder } from '../order-signing' +import { AppDataInfo, LimitOrderParameters } from './types' +import { DEFAULT_QUOTE_VALIDITY } from './consts' + +export function getOrderToSign(from: string, params: LimitOrderParameters, appData: AppDataInfo): UnsignedOrder { + const { + sellAmount, + buyAmount, + sellToken, + sellTokenDecimals, + buyToken, + buyTokenDecimals, + kind, + networkCostsAmount, + partiallyFillable = false, + slippageBps = 0, + partnerFee, + validFor, + } = params + + const receiver = params.receiver || from + const validTo = params.validTo || Math.floor(Date.now() / 1000) + (validFor || DEFAULT_QUOTE_VALIDITY) + const { appDataKeccak256 } = appData + + const orderParams: OrderParameters = { + sellToken, + buyToken, + sellAmount, + buyAmount, + receiver, + validTo, + kind, + feeAmount: networkCostsAmount, + appData: appDataKeccak256, + partiallyFillable, + } + + const { afterSlippage } = getQuoteAmountsAndCosts({ + orderParams, + slippagePercentBps: slippageBps, + partnerFeeBps: partnerFee?.bps, + sellDecimals: sellTokenDecimals, + buyDecimals: buyTokenDecimals, + }) + + return { + sellToken, + buyToken, + sellAmount: afterSlippage.sellAmount.toString(), + buyAmount: afterSlippage.buyAmount.toString(), + validTo, + kind, + partiallyFillable, + appData: appDataKeccak256, + receiver, + feeAmount: '0', + } +} diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts new file mode 100644 index 00000000..080dc7a8 --- /dev/null +++ b/src/trading/getQuote.ts @@ -0,0 +1,95 @@ +import { AppDataInfo, SwapAdvancedSettings, SwapParameters } from './types' +import { DEFAULT_QUOTE_VALIDITY, log } from './consts' +import { ethers } from 'ethers' +import { + getQuoteAmountsAndCosts, + OrderBookApi, + OrderQuoteRequest, + OrderQuoteResponse, + OrderQuoteSideKindBuy, + OrderQuoteSideKindSell, + PriceQuality, + QuoteAmountsAndCosts, + SigningScheme, +} from '../order-book' +import { buildAppData } from './appDataUtils' + +export interface GetQuoteResult { + amountsAndCosts: QuoteAmountsAndCosts + quoteResponse: OrderQuoteResponse + appDataInfo: AppDataInfo + orderBookApi: OrderBookApi + signer: ethers.Signer +} + +export async function getQuote( + params: SwapParameters, + advancedSettings?: SwapAdvancedSettings +): Promise { + const { + appCode, + chainId, + sellToken, + sellTokenDecimals, + buyToken, + buyTokenDecimals, + amount, + kind, + partnerFee, + validFor = DEFAULT_QUOTE_VALIDITY, + slippageBps = 0, + env = 'prod', + } = params + + log(`Swap ${amount} ${sellToken} for ${buyToken} on chain ${chainId}`) + + const signer = typeof params.signer === 'string' ? new ethers.Wallet(params.signer) : params.signer + const orderBookApi = new OrderBookApi({ chainId, env }) + + const from = await signer.getAddress() + const receiver = params.receiver || from + const isSell = kind === 'sell' + + log('Building app data...') + + const appDataInfo = await buildAppData( + { + slippageBps, + orderClass: 'market', + appCode, + }, + advancedSettings?.appData + ) + + const { appDataKeccak256, fullAppData } = appDataInfo + + const quoteRequest: OrderQuoteRequest = { + from, + sellToken, + buyToken, + receiver, + validFor, + appData: fullAppData, + appDataHash: appDataKeccak256, + priceQuality: PriceQuality.OPTIMAL, + signingScheme: SigningScheme.EIP712, + ...(isSell + ? { kind: OrderQuoteSideKindSell.SELL, sellAmountBeforeFee: amount } + : { kind: OrderQuoteSideKindBuy.BUY, buyAmountAfterFee: amount }), + ...advancedSettings?.quoteRequest, + } + + log('Getting quote...') + + const quoteResponse = await orderBookApi.getQuote(quoteRequest) + + const amountsAndCosts = getQuoteAmountsAndCosts({ + orderParams: quoteResponse.quote, + slippagePercentBps: slippageBps, + partnerFeeBps: partnerFee?.bps, + sellDecimals: sellTokenDecimals, + buyDecimals: buyTokenDecimals, + }) + + return { amountsAndCosts, quoteResponse, appDataInfo, orderBookApi, signer } +} diff --git a/src/trading/index.ts b/src/trading/index.ts index 7404c257..613f868a 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -1,2 +1,6 @@ +export * from './quoteUtils' +export * from './types' +export { getQuote } from './getQuote' export { postSwapOrder } from './postSwapOrder' export { postLimitOrder } from './postLimitOrder' +export { postCoWProtocolTrade } from './postTrade' diff --git a/src/trading/postLimitOrder.ts b/src/trading/postLimitOrder.ts index f4370dac..d09e4657 100644 --- a/src/trading/postLimitOrder.ts +++ b/src/trading/postLimitOrder.ts @@ -22,7 +22,7 @@ export async function postLimitOrder(params: LimitOrderParameters, advancedSetti const signer = typeof params.signer === 'string' ? new ethers.Wallet(params.signer) : params.signer const orderBookApi = new OrderBookApi({ chainId, env }) - const feeAmount = '0' + const networkCostsAmount = '0' log('Building app data...') @@ -35,16 +35,11 @@ export async function postLimitOrder(params: LimitOrderParameters, advancedSetti advancedSettings?.appData ) - await postCoWProtocolTrade( - orderBookApi, - signer, - appDataInfo, - { - ...params, - quoteId, - sellAmount, - buyAmount, - }, - feeAmount - ) + await postCoWProtocolTrade(orderBookApi, signer, appDataInfo, { + ...params, + quoteId, + sellAmount, + buyAmount, + networkCostsAmount, + }) } diff --git a/src/trading/postSwapOrder.ts b/src/trading/postSwapOrder.ts index ae4e5ec0..97713d5e 100644 --- a/src/trading/postSwapOrder.ts +++ b/src/trading/postSwapOrder.ts @@ -1,82 +1,21 @@ import { SwapAdvancedSettings, SwapParameters } from './types' -import { DEFAULT_QUOTE_VALIDITY, log } from './consts' -import { ethers } from 'ethers' -import { - OrderBookApi, - OrderQuoteRequest, - OrderQuoteSideKindBuy, - OrderQuoteSideKindSell, - PriceQuality, - SigningScheme, -} from '../order-book' -import { buildAppData } from './appDataUtils' + import { postCoWProtocolTrade } from './postTrade' +import { getQuote } from './getQuote' export async function postSwapOrder(params: SwapParameters, advancedSettings?: SwapAdvancedSettings) { const { - appCode, - chainId, - sellToken, - buyToken, - amount, - kind, - validFor = DEFAULT_QUOTE_VALIDITY, - slippageBps = 0, - env = 'prod', - } = params - - log(`Swap ${amount} ${sellToken} for ${buyToken} on chain ${chainId}`) - - const signer = typeof params.signer === 'string' ? new ethers.Wallet(params.signer) : params.signer - const orderBookApi = new OrderBookApi({ chainId, env }) - - const from = await signer.getAddress() - const receiver = params.receiver || from - const isSell = kind === 'sell' - - log('Building app data...') - - const appDataInfo = await buildAppData( - { - slippageBps, - orderClass: 'market', - appCode, - }, - advancedSettings?.appData - ) - - const { appDataKeccak256, fullAppData } = appDataInfo - - const quoteRequest: OrderQuoteRequest = { - from, - sellToken, - buyToken, - receiver, - validFor, - appData: fullAppData, - appDataHash: appDataKeccak256, - priceQuality: PriceQuality.OPTIMAL, - signingScheme: SigningScheme.EIP712, - ...(isSell - ? { kind: OrderQuoteSideKindSell.SELL, sellAmountBeforeFee: amount } - : { kind: OrderQuoteSideKindBuy.BUY, buyAmountAfterFee: amount }), - ...advancedSettings?.quoteRequest, - } - - log('Getting quote...') - - const { quote, id: quoteId } = await orderBookApi.getQuote(quoteRequest) - - await postCoWProtocolTrade( orderBookApi, signer, + quoteResponse: { quote, id: quoteId }, appDataInfo, - { - ...params, - quoteId, - sellAmount: quote.sellAmount, - buyAmount: quote.buyAmount, - }, - quote.feeAmount - ) + } = await getQuote(params, advancedSettings) + + await postCoWProtocolTrade(orderBookApi, signer, appDataInfo, { + ...params, + quoteId, + sellAmount: quote.sellAmount, + buyAmount: quote.buyAmount, + networkCostsAmount: quote.feeAmount, + }) } diff --git a/src/trading/postTrade.ts b/src/trading/postTrade.ts index 68344f37..ee5c2a6c 100644 --- a/src/trading/postTrade.ts +++ b/src/trading/postTrade.ts @@ -1,68 +1,22 @@ -import { getQuoteAmountsAndCosts, OrderBookApi, OrderCreation } from '../order-book' +import { OrderBookApi, OrderCreation } from '../order-book' import { ethers } from 'ethers' import { AppDataInfo, LimitOrderParameters } from './types' -import { DEFAULT_QUOTE_VALIDITY, log, SIGN_SCHEME_MAP } from './consts' -import { OrderSigningUtils, UnsignedOrder } from '../order-signing' +import { log, SIGN_SCHEME_MAP } from './consts' +import { OrderSigningUtils } from '../order-signing' +import { getOrderToSign } from './getOrderToSign' export async function postCoWProtocolTrade( orderBookApi: OrderBookApi, signer: ethers.Signer, appData: AppDataInfo, - params: LimitOrderParameters, - feeAmount: string + params: LimitOrderParameters ): Promise { - const { - chainId, - sellToken, - sellTokenDecimals, - buyToken, - buyTokenDecimals, - sellAmount, - buyAmount, - kind, - partiallyFillable = false, - quoteId = null, - validFor, - slippageBps = 0, - } = params + const { chainId, quoteId = null } = params + const { appDataKeccak256, fullAppData } = appData - const validTo = params.validTo || Math.floor(Date.now() / 1000) + (validFor || DEFAULT_QUOTE_VALIDITY) const from = await signer.getAddress() - const receiver = params.receiver || from - const { appDataKeccak256, fullAppData, doc } = appData - const partnerFeeBps = doc?.metadata?.partnerFee?.bps - const { afterSlippage } = getQuoteAmountsAndCosts({ - orderParams: { - sellToken, - buyToken, - sellAmount, - buyAmount, - receiver, - validTo, - kind, - feeAmount, - appData: appDataKeccak256, - partiallyFillable, - }, - slippagePercentBps: slippageBps, - partnerFeeBps, - sellDecimals: sellTokenDecimals, - buyDecimals: buyTokenDecimals, - }) - - const orderToSign: UnsignedOrder = { - sellToken, - buyToken, - sellAmount: afterSlippage.sellAmount.toString(), - buyAmount: afterSlippage.buyAmount.toString(), - validTo, - kind, - partiallyFillable, - appData: appDataKeccak256, - receiver, - feeAmount: '0', - } + const orderToSign = getOrderToSign(from, params, appData) log('Signing order...') diff --git a/src/trading/quoteUtils.ts b/src/trading/quoteUtils.ts new file mode 100644 index 00000000..371ca194 --- /dev/null +++ b/src/trading/quoteUtils.ts @@ -0,0 +1,23 @@ +import { getOrderToSign } from './getOrderToSign' +import { GetQuoteResult } from './getQuote' +import { LimitOrderParameters, SwapParameters } from './types' +import { UnsignedOrder } from '../order-signing' +import { OrderQuoteResponse } from '../order-book' + +export function swapParamsToLimitOrderParams( + params: SwapParameters, + { quote: { sellAmount, buyAmount, feeAmount } }: OrderQuoteResponse +): LimitOrderParameters { + return { ...params, sellAmount, buyAmount, networkCostsAmount: feeAmount } +} + +export async function getOrderToSignFromQuoteResult( + quoteResult: GetQuoteResult, + params: SwapParameters +): Promise { + const { signer, appDataInfo } = quoteResult + const from = await signer.getAddress() + const order = swapParamsToLimitOrderParams(params, quoteResult.quoteResponse) + + return getOrderToSign(from, order, appDataInfo) +} diff --git a/src/trading/types.ts b/src/trading/types.ts index 71e384f8..fda2a2b5 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -18,6 +18,7 @@ export interface TradeOptionalParameters { slippageBps?: number receiver?: string validFor?: number + partnerFee?: latest.PartnerFee } export interface TraderParameters { @@ -33,6 +34,7 @@ export interface SwapParameters extends TraderParameters, TradeParameters {} export interface LimitOrderParameters extends TraderParameters, Omit { sellAmount: string buyAmount: string + networkCostsAmount: string validTo?: number quoteId?: number } From 775e687e26ca7d0c283d361e75f2726074428153 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 28 Jun 2024 13:11:27 +0500 Subject: [PATCH 05/67] chore: trade sdk examples --- examples/nodejs/src/index.ts | 1 + src/trading/README.md | 81 ++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 src/trading/README.md diff --git a/examples/nodejs/src/index.ts b/examples/nodejs/src/index.ts index 76ee3561..e5165777 100644 --- a/examples/nodejs/src/index.ts +++ b/examples/nodejs/src/index.ts @@ -36,6 +36,7 @@ const privateKey = 'xxx' buyTokenDecimals: 18, sellAmount: '120000000000000000', buyAmount: '66600000000000000000', + networkCostsAmount: '0', }) })() diff --git a/src/trading/README.md b/src/trading/README.md new file mode 100644 index 00000000..ffafaddb --- /dev/null +++ b/src/trading/README.md @@ -0,0 +1,81 @@ +# Trading SDK + +## Swap + +```typescript +import { + getQuote, + getOrderToSignFromQuoteResult, + postCoWProtocolTrade, + swapParamsToLimitOrderParams, + SupportedChainId, + OrderKind, + SwapParameters +} from '@cowprotocol/sdk' + +const swapParameters: SwapParameters = { + chainId: SupportedChainId.SEPOLIA, + signer: '', + appCode: 'my-trade-sdk-app', + + kind: OrderKind.SELL, + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '120000000000000000', + slippageBps: '500', // 5% +} + +const getQuoteResult = await getQuote(swapParameters) + +console.log('You will get at least: ', getQuoteResult.amountsAndCosts.afterSlippage.buyAmount) + +const orderToSign = await getOrderToSignFromQuoteResult(getQuoteResult, swapParameters) + +console.log('Order to sign: ', orderToSign) + +const { orderBookApi, signer, appDataInfo, quoteResponse } = getQuoteResult + +const orderId = await postCoWProtocolTrade( + orderBookApi, + signer, + appDataInfo, + swapParamsToLimitOrderParams(swapParameters, quoteResponse) +) + +console.log('Order created, id: ', orderId) +``` + +## Limit order + +```typescript +import { + getQuote, + getOrderToSignFromQuoteResult, + postCoWProtocolTrade, + swapParamsToLimitOrderParams, + SupportedChainId, + OrderKind, + LimitOrderParameters +} from '@cowprotocol/sdk' + +const limitOrderParameters: LimitOrderParameters = { + chainId: SupportedChainId.SEPOLIA, + signer: '', + appCode: 'my-trade-sdk-app', + + kind: OrderKind.BUY, + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + sellAmount: '120000000000000000', + buyAmount: '66600000000000000000', + networkCostsAmount: '0' +} + +const orderId = await postLimitOrder(limitOrderParameters) + +console.log('Order created, id: ', orderId) +``` From bbece96379aec1acdf663411157f599c1b8831d9 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 5 Jul 2024 19:52:34 +0500 Subject: [PATCH 06/67] docs: trading SDK docs --- examples/cra/tsconfig.json | 2 +- examples/vanilla/src/formState.ts | 10 +- examples/vanilla/src/index.ts | 37 +-- src/trading/README.md | 230 +++++++++++++++--- src/trading/consts.ts | 2 +- src/trading/getQuote.ts | 22 +- src/trading/index.ts | 7 +- .../{postTrade.ts => postCoWProtocolTrade.ts} | 0 src/trading/postLimitOrder.ts | 4 +- src/trading/postSwapOrder.ts | 29 ++- src/trading/quoteUtils.ts | 14 -- src/trading/tradingSdk.ts | 36 +++ src/trading/types.ts | 12 +- src/trading/utils.ts | 9 + 14 files changed, 313 insertions(+), 101 deletions(-) rename src/trading/{postTrade.ts => postCoWProtocolTrade.ts} (100%) create mode 100644 src/trading/tradingSdk.ts create mode 100644 src/trading/utils.ts diff --git a/examples/cra/tsconfig.json b/examples/cra/tsconfig.json index 9c7d4a8a..98509a17 100644 --- a/examples/cra/tsconfig.json +++ b/examples/cra/tsconfig.json @@ -20,7 +20,7 @@ "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" - }, + }, "include": [ "src" ] diff --git a/examples/vanilla/src/formState.ts b/examples/vanilla/src/formState.ts index 5d9ab500..9fd9a839 100644 --- a/examples/vanilla/src/formState.ts +++ b/examples/vanilla/src/formState.ts @@ -1,8 +1,6 @@ -import { OrderKind, SupportedChainId, SwapParameters } from '../../../src' +import { OrderKind, SupportedChainId, SwapParameters, TradeParameters } from '../../../src' import { TOKENS } from './tokens' -const appCode = 'trade-sdk-example' - interface FormState { privateKey: string chainId: string @@ -17,9 +15,8 @@ export const getFormState = (): FormState => { return Object.fromEntries(new FormData(document.getElementById('form') as HTMLFormElement)) as unknown as FormState } -export const getSwapParameters = (): SwapParameters => { +export const getTradeParameters = (): TradeParameters => { const { - privateKey, slippageBps: _slippageBps, chainId: _chainId, sellToken: _sellToken, @@ -36,9 +33,6 @@ export const getSwapParameters = (): SwapParameters => { const slippageBps = _slippageBps ? +_slippageBps : undefined return { - appCode, - signer: privateKey, - chainId, sellToken: sellToken.address, sellTokenDecimals: sellToken.decimals, buyToken: buyToken.address, diff --git a/examples/vanilla/src/index.ts b/examples/vanilla/src/index.ts index e20bc74f..de9bbb00 100644 --- a/examples/vanilla/src/index.ts +++ b/examples/vanilla/src/index.ts @@ -1,18 +1,19 @@ -import { SupportedChainId, getQuote, UnsignedOrder } from '../../../src' +import { SupportedChainId } from '../../../src' -import { getOrderToSignFromQuoteResult, swapParamsToLimitOrderParams, postCoWProtocolTrade } from '../../../src/trading' +import { TradingSdk, QuoteAndPost } from '../../../src/trading' import { TOKENS } from './tokens' import { atomsToAmount } from './utils' import { pageHtml } from './pageHtml' import { pageActions, printResult } from './pageActions' -import { GetQuoteResult } from '../../../src/trading/getQuote' -import { getFormState, getSwapParameters } from './formState' +import { getFormState, getTradeParameters } from './formState' import './styles.css' +const appCode = 'trade-sdk-example' + // Run the example ;(async function () { - let getQuoteResult: GetQuoteResult | null = null + let quoteAndPost: QuoteAndPost | null = null // Render page const page = pageHtml() @@ -21,7 +22,7 @@ import './styles.css' // Bind actions to the page pageActions({ onFormReset() { - getQuoteResult = null + quoteAndPost = null }, async onGetQuote() { const { @@ -31,6 +32,7 @@ import './styles.css' buyToken: _buyToken, amount: _amount, kind, + privateKey, } = getFormState() const chainId: SupportedChainId = +_chainId @@ -38,13 +40,19 @@ import './styles.css' const sellToken = TOKENS[chainId].find((t) => t.address === _sellToken) const buyToken = TOKENS[chainId].find((t) => t.address === _buyToken) - getQuoteResult = await getQuote(getSwapParameters()) + const sdk = new TradingSdk({ + chainId, + signer: privateKey, + appCode, + }) + + quoteAndPost = await sdk.getQuote(getTradeParameters()) const { amountsAndCosts: { beforeNetworkCosts, afterSlippage }, - } = getQuoteResult + } = quoteAndPost.quoteResults - console.log('Quote results:', getQuoteResult) + console.log('Quote results:', quoteAndPost.quoteResults) const outputToken = isSell ? buyToken : sellToken @@ -61,7 +69,7 @@ import './styles.css' `) }, async onConfirmOrder() { - const orderToSign = await getOrderToSignFromQuoteResult(getQuoteResult, getSwapParameters()) + const orderToSign = quoteAndPost.quoteResults.orderToSign printResult(` You are going to sign: @@ -69,14 +77,7 @@ import './styles.css' `) }, async onSignAndSendOrder() { - const { orderBookApi, signer, appDataInfo, quoteResponse } = getQuoteResult - - const orderId = await postCoWProtocolTrade( - orderBookApi, - signer, - appDataInfo, - swapParamsToLimitOrderParams(getSwapParameters(), quoteResponse) - ) + const orderId = await quoteAndPost.postSwapOrderFromQuote() printResult(`Order created, id: ${orderId}`) }, diff --git a/src/trading/README.md b/src/trading/README.md index ffafaddb..5fbde60d 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -1,70 +1,171 @@ # Trading SDK -## Swap +The CoW Protocol provides very flexible and powerful trading capabilities. +However, this flexibility comes with a cost: the complexity of the protocol. +This SDK serves to simplify the interaction with the CoW Protocol. +It will put all necessary parameters to your order, calculates proper amounts, and signs the order. + +> You can find an example of the SDK usage in the [examples](../../examples/vanilla/src/index.ts). + +### What constitutes the complexity? + + - [app-data](https://docs.cow.fi/cow-protocol/reference/sdks/app-data) (order's metadata) + - [order signing](https://docs.cow.fi/cow-protocol/reference/sdks/cow-sdk/classes/OrderSigningUtils) + - network costs, partner fee and slippage + - order parameters (validTo, partiallyFillable, etc.) + - quote API (priceQuality, signingScheme, etc.) + - order kind (sell/buy) + - order class (swap/limit/and others) + +## TradingSdk + +The SDK provides three main functions: + - `postSwapOrder` - get quote with market price and create a swap order + - `postLimitOrder` - create a limit order + - `getQuote` - fetch a quote for a swap order + +### Initialization + +The SDK requires the following parameters: + - `chainId` - one of supported chain ids (see [`SupportedChainId`](../common/chains.ts)) + - `signer` - private key or ethers signer. The signer is used to sign the order. If you use a private key, the SDK will create an ethers signer from it. If you use an ethers signer, the SDK will use it directly. + - `appCode` - a unique identifier for your application. It is used to identify orders created by your application. + +#### Example +```typescript +import { SupportedChainId, TradingSdk } from '@cowprotocol/sdk' + +const sdk = new TradingSdk({ + chainId: SupportedChainId.SEPOLIA, + signer: '', + appCode: '', +}) +``` + +### postSwapOrder + +This function fetches a quote for a swap order and just creates the order. + +The parameters required are: + - `kind` - the order kind (sell/buy) + - `sellToken` - the sell token address + - `sellTokenDecimals` - the sell token decimals + - `buyToken` - the buy token address + - `buyTokenDecimals` - the buy token decimals + - `amount` - the amount to sell/buy in atoms + +#### Example ```typescript import { - getQuote, - getOrderToSignFromQuoteResult, - postCoWProtocolTrade, - swapParamsToLimitOrderParams, SupportedChainId, OrderKind, - SwapParameters + TradeParameters, + TradingSdk } from '@cowprotocol/sdk' -const swapParameters: SwapParameters = { +const sdk = new TradingSdk({ chainId: SupportedChainId.SEPOLIA, signer: '', - appCode: 'my-trade-sdk-app', + appCode: '', +}) - kind: OrderKind.SELL, +const parameters: TradeParameters = { + kind: OrderKind.BUY, sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', sellTokenDecimals: 18, buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', buyTokenDecimals: 18, - amount: '120000000000000000', - slippageBps: '500', // 5% + amount: '120000000000000000' } -const getQuoteResult = await getQuote(swapParameters) +const orderId = await sdk.postSwapOrder(parameters) -console.log('You will get at least: ', getQuoteResult.amountsAndCosts.afterSlippage.buyAmount) +console.log('Order created, id: ', orderId) +``` -const orderToSign = await getOrderToSignFromQuoteResult(getQuoteResult, swapParameters) +### getQuote -console.log('Order to sign: ', orderToSign) +In case if you want to get a quote and only then create an order, you can use the `getQuote` function. -const { orderBookApi, signer, appDataInfo, quoteResponse } = getQuoteResult +The parameters required are the same as for the `postSwapOrder` function. -const orderId = await postCoWProtocolTrade( - orderBookApi, - signer, - appDataInfo, - swapParamsToLimitOrderParams(swapParameters, quoteResponse) -) +The function returns a quote object with the following fields: + - `swapParameters` - the parameters used to get the quote + - `amountsAndCosts` - the order sell/buy amounts including network costs, fees and slippage + - `orderToSign` - the order to sign + - `quoteResponse` - DTO from [quote API](https://api.cow.fi/docs/#/default/post_api_v1_quote) + - `appDataInfo` - [order's metadata](https://docs.cow.fi/cow-protocol/reference/sdks/app-data) + - `orderBookApi` - instance of [`OrderBookApi`](../order-book/api.ts) + - `signer` - instance if Ethers signer -console.log('Order created, id: ', orderId) +Another parameter is returned by this function is `postSwapOrderFromQuote`. +It can be used to create an order from the received quote. + +#### Example + +```typescript +import { + SupportedChainId, + OrderKind, + TradeParameters, + TradingSdk +} from '@cowprotocol/sdk' + +const sdk = new TradingSdk({ + chainId: SupportedChainId.SEPOLIA, + signer: '', + appCode: '', +}) + +const parameters: TradeParameters = { + kind: OrderKind.BUY, + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '120000000000000000' +} + +const { quoteResults, postSwapOrderFromQuote } = await sdk.getQuote(parameters) + +const buyAmount = quoteResults.amountsAndCosts.afterSlippage.buyAmount + +if (confirm(`You will get at least: ${buyAmount}, ok?`)) { + const orderId = await postSwapOrderFromQuote() + + console.log('Order created, id: ', orderId) +} ``` -## Limit order +### postLimitOrder + +This function is simpler than the `postSwapOrder` function, because it doesn't require a quote. + +You need to provide the following parameters: + - `kind` - the order kind (sell/buy) + - `sellToken` - the sell token address + - `sellTokenDecimals` - the sell token decimals + - `buyToken` - the buy token address + - `buyTokenDecimals` - the buy token decimals + - `sellAmount` - the amount to sell in atoms + - `buyAmount` - the amount to buy in atoms ```typescript import { - getQuote, - getOrderToSignFromQuoteResult, - postCoWProtocolTrade, - swapParamsToLimitOrderParams, SupportedChainId, OrderKind, - LimitOrderParameters + LimitTradeParameters, + TradingSdk } from '@cowprotocol/sdk' -const limitOrderParameters: LimitOrderParameters = { +const sdk = new TradingSdk({ chainId: SupportedChainId.SEPOLIA, signer: '', - appCode: 'my-trade-sdk-app', + appCode: '', +}) +const limitOrderParameters: LimitTradeParameters = { kind: OrderKind.BUY, sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', sellTokenDecimals: 18, @@ -72,10 +173,73 @@ const limitOrderParameters: LimitOrderParameters = { buyTokenDecimals: 18, sellAmount: '120000000000000000', buyAmount: '66600000000000000000', - networkCostsAmount: '0' } -const orderId = await postLimitOrder(limitOrderParameters) +const orderId = await sdk.postLimitOrder(limitOrderParameters) + +console.log('Order created, id: ', orderId) +``` + +### Advanced swap order creation + +By default, the SDK requires only the basic parameters to create an order. +However, you can provide additional parameters to customize the order creation. + +#### Swap + +1. `quoteRequest` - the quote request object. It is used to get a quote from the quote API ([read more](https://docs.cow.fi/cow-protocol/reference/sdks/cow-sdk/modules#orderquoterequest)) +2. `appData` - the order's metadata ([read more](https://docs.cow.fi/cow-protocol/reference/sdks/app-data/modules#appdataparams)) + +##### Example + +```typescript +import { + SupportedChainId, + OrderKind, + TradeParameters, + TradingSdk, + SwapAdvancedSettings, + PriceQuality +} from '@cowprotocol/sdk' + +const sdk = new TradingSdk({ + chainId: SupportedChainId.SEPOLIA, + signer: '', + appCode: '', +}) + +const parameters: TradeParameters = { + kind: OrderKind.BUY, + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '120000000000000000' +} + +const advancedSettings: SwapAdvancedSettings = { + quoteRequest: { + priceQuality: PriceQuality.FAST, + validFor: 120, + }, + appData: { + hooks: { + version: 1, + pre: [ + { + target: '0xdef1ca1fb7fbcdc777520aa7f396b4e015f497ab', + callData: '0x70a08231000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045', + gasLimit: 21000 + } + ] + } + }, +} +const orderId = await sdk.postSwapOrder(parameters) console.log('Order created, id: ', orderId) ``` + +#### Limit order + +Same as for the swap order but without the `quoteRequest` parameter. diff --git a/src/trading/consts.ts b/src/trading/consts.ts index ec3072b6..d3c69f3f 100644 --- a/src/trading/consts.ts +++ b/src/trading/consts.ts @@ -1,6 +1,6 @@ import { EcdsaSigningScheme, SigningScheme } from '../order-book' -export const log = (text: string) => console.log(`[SDK] ${text}`) +export const log = (text: string) => console.log(`[COW TRADING SDK] ${text}`) export const DEFAULT_QUOTE_VALIDITY = 60 * 10 // 10 min diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index 080dc7a8..bb9a8ad2 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -13,9 +13,14 @@ import { SigningScheme, } from '../order-book' import { buildAppData } from './appDataUtils' +import { UnsignedOrder } from '../order-signing' +import { getOrderToSign } from './getOrderToSign' +import { swapParamsToLimitOrderParams } from './utils' -export interface GetQuoteResult { +export interface QuoteResults { + swapParameters: SwapParameters amountsAndCosts: QuoteAmountsAndCosts + orderToSign: UnsignedOrder quoteResponse: OrderQuoteResponse appDataInfo: AppDataInfo orderBookApi: OrderBookApi @@ -23,9 +28,9 @@ export interface GetQuoteResult { } export async function getQuote( - params: SwapParameters, + swapParameters: SwapParameters, advancedSettings?: SwapAdvancedSettings -): Promise { +): Promise { const { appCode, chainId, @@ -39,15 +44,16 @@ export async function getQuote( validFor = DEFAULT_QUOTE_VALIDITY, slippageBps = 0, env = 'prod', - } = params + } = swapParameters log(`Swap ${amount} ${sellToken} for ${buyToken} on chain ${chainId}`) - const signer = typeof params.signer === 'string' ? new ethers.Wallet(params.signer) : params.signer + const signer = + typeof swapParameters.signer === 'string' ? new ethers.Wallet(swapParameters.signer) : swapParameters.signer const orderBookApi = new OrderBookApi({ chainId, env }) const from = await signer.getAddress() - const receiver = params.receiver || from + const receiver = swapParameters.receiver || from const isSell = kind === 'sell' log('Building app data...') @@ -91,5 +97,7 @@ export async function getQuote( buyDecimals: buyTokenDecimals, }) - return { amountsAndCosts, quoteResponse, appDataInfo, orderBookApi, signer } + const orderToSign = getOrderToSign(from, swapParamsToLimitOrderParams(swapParameters, quoteResponse), appDataInfo) + + return { amountsAndCosts, quoteResponse, appDataInfo, orderBookApi, signer, orderToSign, swapParameters } } diff --git a/src/trading/index.ts b/src/trading/index.ts index 613f868a..49c95d00 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -1,6 +1,9 @@ export * from './quoteUtils' export * from './types' +export * from './tradingSdk' + export { getQuote } from './getQuote' -export { postSwapOrder } from './postSwapOrder' +export { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' export { postLimitOrder } from './postLimitOrder' -export { postCoWProtocolTrade } from './postTrade' +export { postCoWProtocolTrade } from './postCoWProtocolTrade' +export { getOrderToSign } from './getOrderToSign' diff --git a/src/trading/postTrade.ts b/src/trading/postCoWProtocolTrade.ts similarity index 100% rename from src/trading/postTrade.ts rename to src/trading/postCoWProtocolTrade.ts diff --git a/src/trading/postLimitOrder.ts b/src/trading/postLimitOrder.ts index d09e4657..c104d04e 100644 --- a/src/trading/postLimitOrder.ts +++ b/src/trading/postLimitOrder.ts @@ -3,7 +3,7 @@ import { log } from './consts' import { ethers } from 'ethers' import { OrderBookApi } from '../order-book' import { buildAppData } from './appDataUtils' -import { postCoWProtocolTrade } from './postTrade' +import { postCoWProtocolTrade } from './postCoWProtocolTrade' export async function postLimitOrder(params: LimitOrderParameters, advancedSettings?: LimitOrderAdvancedSettings) { const { @@ -35,7 +35,7 @@ export async function postLimitOrder(params: LimitOrderParameters, advancedSetti advancedSettings?.appData ) - await postCoWProtocolTrade(orderBookApi, signer, appDataInfo, { + return postCoWProtocolTrade(orderBookApi, signer, appDataInfo, { ...params, quoteId, sellAmount, diff --git a/src/trading/postSwapOrder.ts b/src/trading/postSwapOrder.ts index 97713d5e..6e3b0a06 100644 --- a/src/trading/postSwapOrder.ts +++ b/src/trading/postSwapOrder.ts @@ -1,21 +1,24 @@ import { SwapAdvancedSettings, SwapParameters } from './types' -import { postCoWProtocolTrade } from './postTrade' -import { getQuote } from './getQuote' +import { postCoWProtocolTrade } from './postCoWProtocolTrade' +import { getQuote, QuoteResults } from './getQuote' +import { swapParamsToLimitOrderParams } from './utils' export async function postSwapOrder(params: SwapParameters, advancedSettings?: SwapAdvancedSettings) { - const { + return postSwapOrderFromQuote(await getQuote(params, advancedSettings)) +} + +export async function postSwapOrderFromQuote({ + orderBookApi, + signer, + appDataInfo, + quoteResponse, + swapParameters, +}: QuoteResults) { + return postCoWProtocolTrade( orderBookApi, signer, - quoteResponse: { quote, id: quoteId }, appDataInfo, - } = await getQuote(params, advancedSettings) - - await postCoWProtocolTrade(orderBookApi, signer, appDataInfo, { - ...params, - quoteId, - sellAmount: quote.sellAmount, - buyAmount: quote.buyAmount, - networkCostsAmount: quote.feeAmount, - }) + swapParamsToLimitOrderParams(swapParameters, quoteResponse) + ) } diff --git a/src/trading/quoteUtils.ts b/src/trading/quoteUtils.ts index 371ca194..cb4a72a8 100644 --- a/src/trading/quoteUtils.ts +++ b/src/trading/quoteUtils.ts @@ -1,7 +1,4 @@ -import { getOrderToSign } from './getOrderToSign' -import { GetQuoteResult } from './getQuote' import { LimitOrderParameters, SwapParameters } from './types' -import { UnsignedOrder } from '../order-signing' import { OrderQuoteResponse } from '../order-book' export function swapParamsToLimitOrderParams( @@ -10,14 +7,3 @@ export function swapParamsToLimitOrderParams( ): LimitOrderParameters { return { ...params, sellAmount, buyAmount, networkCostsAmount: feeAmount } } - -export async function getOrderToSignFromQuoteResult( - quoteResult: GetQuoteResult, - params: SwapParameters -): Promise { - const { signer, appDataInfo } = quoteResult - const from = await signer.getAddress() - const order = swapParamsToLimitOrderParams(params, quoteResult.quoteResponse) - - return getOrderToSign(from, order, appDataInfo) -} diff --git a/src/trading/tradingSdk.ts b/src/trading/tradingSdk.ts new file mode 100644 index 00000000..c887b5ea --- /dev/null +++ b/src/trading/tradingSdk.ts @@ -0,0 +1,36 @@ +import { + LimitOrderAdvancedSettings, + LimitTradeParameters, + QuoteAndPost, + SwapAdvancedSettings, + TradeParameters, + TraderParameters, +} from './types' +import { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' +import { postLimitOrder } from './postLimitOrder' +import { getQuote } from './getQuote' + +export class TradingSdk { + constructor(public readonly traderParams: TraderParameters) {} + + async postSwapOrder(params: TradeParameters, advancedSettings?: SwapAdvancedSettings) { + return postSwapOrder(this.mergeParams(params), advancedSettings) + } + + async postLimitOrder(params: LimitTradeParameters, advancedSettings?: LimitOrderAdvancedSettings) { + return postLimitOrder(this.mergeParams(params), advancedSettings) + } + + async getQuote(params: TradeParameters, advancedSettings?: SwapAdvancedSettings): Promise { + const quoteResults = await getQuote(this.mergeParams(params), advancedSettings) + + return { + quoteResults, + postSwapOrderFromQuote: () => postSwapOrderFromQuote(quoteResults), + } + } + + private mergeParams(params: T): T & TraderParameters { + return { ...params, ...this.traderParams } + } +} diff --git a/src/trading/types.ts b/src/trading/types.ts index fda2a2b5..82042c94 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -2,6 +2,7 @@ import { latest, LatestAppDataDocVersion, AppDataParams } from '@cowprotocol/app import { Address, OrderQuoteRequest, OrderKind } from '../order-book' import type { Signer } from '@ethersproject/abstract-signer' import { CowEnv, SupportedChainId } from '../common' +import { QuoteResults } from './getQuote' export interface TradeBaseParameters { kind: OrderKind @@ -31,14 +32,16 @@ export interface TradeParameters extends TradeBaseParameters, TradeOptionalParam export interface SwapParameters extends TraderParameters, TradeParameters {} -export interface LimitOrderParameters extends TraderParameters, Omit { +export interface LimitTradeParameters extends Omit { sellAmount: string buyAmount: string - networkCostsAmount: string + networkCostsAmount: string // TODO: encapsulate the parameter validTo?: number quoteId?: number } +export interface LimitOrderParameters extends TraderParameters, LimitTradeParameters {} + export interface SwapAdvancedSettings { quoteRequest?: Partial> appData?: AppDataParams @@ -48,6 +51,11 @@ export interface LimitOrderAdvancedSettings { appData?: AppDataParams } +export interface QuoteAndPost { + quoteResults: QuoteResults + postSwapOrderFromQuote(): Promise +} + export type AppDataOrderClass = latest.OrderClass['orderClass'] export type AppDataRootSchema = latest.AppDataRootSchema diff --git a/src/trading/utils.ts b/src/trading/utils.ts new file mode 100644 index 00000000..cb4a72a8 --- /dev/null +++ b/src/trading/utils.ts @@ -0,0 +1,9 @@ +import { LimitOrderParameters, SwapParameters } from './types' +import { OrderQuoteResponse } from '../order-book' + +export function swapParamsToLimitOrderParams( + params: SwapParameters, + { quote: { sellAmount, buyAmount, feeAmount } }: OrderQuoteResponse +): LimitOrderParameters { + return { ...params, sellAmount, buyAmount, networkCostsAmount: feeAmount } +} From f27a94d2ba19b4abc1c40e0178a77793a5d95b71 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 5 Jul 2024 20:04:23 +0500 Subject: [PATCH 07/67] chore: encapsulate networkCostsAmount --- src/trading/getOrderToSign.ts | 18 +++++++++++++----- src/trading/index.ts | 1 - src/trading/postCoWProtocolTrade.ts | 5 +++-- src/trading/postLimitOrder.ts | 2 -- src/trading/postSwapOrder.ts | 3 ++- src/trading/quoteUtils.ts | 9 --------- src/trading/types.ts | 1 - src/trading/utils.ts | 4 ++-- 8 files changed, 20 insertions(+), 23 deletions(-) delete mode 100644 src/trading/quoteUtils.ts diff --git a/src/trading/getOrderToSign.ts b/src/trading/getOrderToSign.ts index 3d20c86c..818b72d0 100644 --- a/src/trading/getOrderToSign.ts +++ b/src/trading/getOrderToSign.ts @@ -3,7 +3,16 @@ import { UnsignedOrder } from '../order-signing' import { AppDataInfo, LimitOrderParameters } from './types' import { DEFAULT_QUOTE_VALIDITY } from './consts' -export function getOrderToSign(from: string, params: LimitOrderParameters, appData: AppDataInfo): UnsignedOrder { +interface OrderToSignParams { + from: string + networkCostsAmount: string +} + +export function getOrderToSign( + { from, networkCostsAmount }: OrderToSignParams, + limitOrderParams: LimitOrderParameters, + appData: AppDataInfo +): UnsignedOrder { const { sellAmount, buyAmount, @@ -12,15 +21,14 @@ export function getOrderToSign(from: string, params: LimitOrderParameters, appDa buyToken, buyTokenDecimals, kind, - networkCostsAmount, partiallyFillable = false, slippageBps = 0, partnerFee, validFor, - } = params + } = limitOrderParams - const receiver = params.receiver || from - const validTo = params.validTo || Math.floor(Date.now() / 1000) + (validFor || DEFAULT_QUOTE_VALIDITY) + const receiver = limitOrderParams.receiver || from + const validTo = limitOrderParams.validTo || Math.floor(Date.now() / 1000) + (validFor || DEFAULT_QUOTE_VALIDITY) const { appDataKeccak256 } = appData const orderParams: OrderParameters = { diff --git a/src/trading/index.ts b/src/trading/index.ts index 49c95d00..cb6eba45 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -1,4 +1,3 @@ -export * from './quoteUtils' export * from './types' export * from './tradingSdk' diff --git a/src/trading/postCoWProtocolTrade.ts b/src/trading/postCoWProtocolTrade.ts index ee5c2a6c..674dd2dc 100644 --- a/src/trading/postCoWProtocolTrade.ts +++ b/src/trading/postCoWProtocolTrade.ts @@ -9,14 +9,15 @@ export async function postCoWProtocolTrade( orderBookApi: OrderBookApi, signer: ethers.Signer, appData: AppDataInfo, - params: LimitOrderParameters + params: LimitOrderParameters, + networkCostsAmount = '0' ): Promise { const { chainId, quoteId = null } = params const { appDataKeccak256, fullAppData } = appData const from = await signer.getAddress() - const orderToSign = getOrderToSign(from, params, appData) + const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appData) log('Signing order...') diff --git a/src/trading/postLimitOrder.ts b/src/trading/postLimitOrder.ts index c104d04e..6e9b4d77 100644 --- a/src/trading/postLimitOrder.ts +++ b/src/trading/postLimitOrder.ts @@ -22,7 +22,6 @@ export async function postLimitOrder(params: LimitOrderParameters, advancedSetti const signer = typeof params.signer === 'string' ? new ethers.Wallet(params.signer) : params.signer const orderBookApi = new OrderBookApi({ chainId, env }) - const networkCostsAmount = '0' log('Building app data...') @@ -40,6 +39,5 @@ export async function postLimitOrder(params: LimitOrderParameters, advancedSetti quoteId, sellAmount, buyAmount, - networkCostsAmount, }) } diff --git a/src/trading/postSwapOrder.ts b/src/trading/postSwapOrder.ts index 6e3b0a06..f85562c3 100644 --- a/src/trading/postSwapOrder.ts +++ b/src/trading/postSwapOrder.ts @@ -19,6 +19,7 @@ export async function postSwapOrderFromQuote({ orderBookApi, signer, appDataInfo, - swapParamsToLimitOrderParams(swapParameters, quoteResponse) + swapParamsToLimitOrderParams(swapParameters, quoteResponse), + quoteResponse.quote.feeAmount ) } diff --git a/src/trading/quoteUtils.ts b/src/trading/quoteUtils.ts deleted file mode 100644 index cb4a72a8..00000000 --- a/src/trading/quoteUtils.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { LimitOrderParameters, SwapParameters } from './types' -import { OrderQuoteResponse } from '../order-book' - -export function swapParamsToLimitOrderParams( - params: SwapParameters, - { quote: { sellAmount, buyAmount, feeAmount } }: OrderQuoteResponse -): LimitOrderParameters { - return { ...params, sellAmount, buyAmount, networkCostsAmount: feeAmount } -} diff --git a/src/trading/types.ts b/src/trading/types.ts index 82042c94..e96457b9 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -35,7 +35,6 @@ export interface SwapParameters extends TraderParameters, TradeParameters {} export interface LimitTradeParameters extends Omit { sellAmount: string buyAmount: string - networkCostsAmount: string // TODO: encapsulate the parameter validTo?: number quoteId?: number } diff --git a/src/trading/utils.ts b/src/trading/utils.ts index cb4a72a8..d7eeae2a 100644 --- a/src/trading/utils.ts +++ b/src/trading/utils.ts @@ -3,7 +3,7 @@ import { OrderQuoteResponse } from '../order-book' export function swapParamsToLimitOrderParams( params: SwapParameters, - { quote: { sellAmount, buyAmount, feeAmount } }: OrderQuoteResponse + { quote: { sellAmount, buyAmount } }: OrderQuoteResponse ): LimitOrderParameters { - return { ...params, sellAmount, buyAmount, networkCostsAmount: feeAmount } + return { ...params, sellAmount, buyAmount } } From f82841d11ce4fa26f14568e051369ee544fefa25 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 5 Jul 2024 20:07:12 +0500 Subject: [PATCH 08/67] chore: fix build --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1520a55a..6375cf9b 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "types": "dist/index.d.ts", "scripts": { - "prebuild": "rm -rf dist", + "prebuild": "rm -rf dist && yarn run codegen", "build": "microbundle -f modern,esm,cjs", "start": "microbundle -f modern,esm,cjs watch", "postbuild": "cp package.json dist && cp README.md dist", From 5639517e9a42ac4676b388ae6126f508535eaf20 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 5 Jul 2024 20:09:20 +0500 Subject: [PATCH 09/67] chore: fix build --- src/trading/getQuote.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index bb9a8ad2..ae411486 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -97,7 +97,11 @@ export async function getQuote( buyDecimals: buyTokenDecimals, }) - const orderToSign = getOrderToSign(from, swapParamsToLimitOrderParams(swapParameters, quoteResponse), appDataInfo) + const orderToSign = getOrderToSign( + { from, networkCostsAmount: quoteResponse.quote.feeAmount }, + swapParamsToLimitOrderParams(swapParameters, quoteResponse), + appDataInfo + ) return { amountsAndCosts, quoteResponse, appDataInfo, orderBookApi, signer, orderToSign, swapParameters } } From 94b21ffa5f53d09ca70a008c0db7f2f274105ed1 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 5 Nov 2024 17:18:07 +0500 Subject: [PATCH 10/67] chore: make networkCostsAmount optional --- src/trading/getOrderToSign.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/trading/getOrderToSign.ts b/src/trading/getOrderToSign.ts index 818b72d0..d7844912 100644 --- a/src/trading/getOrderToSign.ts +++ b/src/trading/getOrderToSign.ts @@ -5,11 +5,11 @@ import { DEFAULT_QUOTE_VALIDITY } from './consts' interface OrderToSignParams { from: string - networkCostsAmount: string + networkCostsAmount?: string } export function getOrderToSign( - { from, networkCostsAmount }: OrderToSignParams, + { from, networkCostsAmount = '0' }: OrderToSignParams, limitOrderParams: LimitOrderParameters, appData: AppDataInfo ): UnsignedOrder { From bf87d831087ce571fd76eda1e82503126ce768d5 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 6 Nov 2024 17:09:25 +0500 Subject: [PATCH 11/67] feat: calculate unique OrderId util --- src/common/consts.ts | 29 ++++++++++++++++ src/order-signing/orderSigningUtils.ts | 21 +++++++++-- src/order-signing/utils.ts | 28 +++++++++++++++ src/trading/calculateUniqueOrderId.ts | 48 ++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 src/trading/calculateUniqueOrderId.ts diff --git a/src/common/consts.ts b/src/common/consts.ts index 42bd6704..268ba3b7 100644 --- a/src/common/consts.ts +++ b/src/common/consts.ts @@ -52,3 +52,32 @@ export const EXTENSIBLE_FALLBACK_HANDLER_CONTRACT_ADDRESS = mapAddressToSupporte * An object containing the addresses of the `ComposableCow` contracts for each supported chain. */ export const COMPOSABLE_COW_CONTRACT_ADDRESS = mapAddressToSupportedNetworks(COMPOSABLE_COW) + +/** + * An object containing the addresses of wrapped native currencies for each supported chain. + */ +export const WRAPPED_NATIVE_CURRENCIES: Record = { + [SupportedChainId.MAINNET]: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + [SupportedChainId.GNOSIS_CHAIN]: '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d', + [SupportedChainId.ARBITRUM_ONE]: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + [SupportedChainId.SEPOLIA]: '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14', +} + +/** + * An object containing the addresses of ETH flow contracts for each supported chain. + */ +export const ETH_FLOW_ADDRESSES: Record = { + [SupportedChainId.MAINNET]: '0x40A50cf069e992AA4536211B23F286eF88752187', + [SupportedChainId.GNOSIS_CHAIN]: '0x40A50cf069e992AA4536211B23F286eF88752187', + [SupportedChainId.ARBITRUM_ONE]: '0x552fcecc218158fff20e505c8f3ad24f8e1dd33c', + [SupportedChainId.SEPOLIA]: '0x0b7795E18767259CC253a2dF471db34c72B49516', +} + +// const BARN_ETH_FLOW_ADDRESSES: Record = { +// [SupportedChainId.MAINNET]: '0xD02De8Da0B71E1B59489794F423FaBBa2AdC4d93', +// [SupportedChainId.GNOSIS_CHAIN]: '0xD02De8Da0B71E1B59489794F423FaBBa2AdC4d93', +// [SupportedChainId.ARBITRUM_ONE]: '0x6dfe75b5ddce1ade279d4fa6bd6aef3cbb6f49db', +// [SupportedChainId.SEPOLIA]: '0x2671994c7D224ac4799ac2cf6Ef9EF187d42C69f', +// } + +export const MAX_VALID_TO_EPOCH = 4294967295 // Max uint32 (Feb 07 2106 07:28:15 GMT+0100) diff --git a/src/order-signing/orderSigningUtils.ts b/src/order-signing/orderSigningUtils.ts index 1259571f..4dbd5879 100644 --- a/src/order-signing/orderSigningUtils.ts +++ b/src/order-signing/orderSigningUtils.ts @@ -1,6 +1,6 @@ import type { SupportedChainId } from '../common' import type { Signer } from '@ethersproject/abstract-signer' -import type { TypedDataDomain } from '@cowprotocol/contracts' +import type { Order, TypedDataDomain, OrderUidParams } from '@cowprotocol/contracts' import type { SigningResult, UnsignedOrder } from './types' const getSignUtils = () => import('./utils') @@ -76,7 +76,7 @@ export class OrderSigningUtils { /** * Sign a cancellation message of multiple order intents with the specified signer. * @param {string[]} orderUids An array of `orderUid` to cancel. - * @param {SupportedChainId} chainId The CoW Protocol protocol `chainId` context that's being used. + * @param {SupportedChainId} chainId The CoW Protocol `chainId` context that's being used. * @param {Signer} signer The signer who initially placed the order intents. * @returns {Promise} Encoded signature including signing scheme for the cancellation. */ @@ -91,7 +91,7 @@ export class OrderSigningUtils { /** * Get the EIP-712 typed domain data being used for signing. - * @param {SupportedChainId} chainId The CoW Protocol protocol `chainId` context that's being used. + * @param {SupportedChainId} chainId The CoW Protocol `chainId` context that's being used. * @return The EIP-712 typed domain data. * @see https://eips.ethereum.org/EIPS/eip-712 */ @@ -100,6 +100,21 @@ export class OrderSigningUtils { return getDomain(chainId) } + /** + * Hashes the order intent and generate deterministic order ID. + * @param {SupportedChainId} chainId The CoW Protocol `chainId` context that's being used. + * @param {Order} order order to sign + * @param {Pick} params order unique identifier parameters. + */ + static async generateOrderId( + chainId: SupportedChainId, + order: Order, + params: Pick + ): Promise<{ orderId: string; orderDigest: string }> { + const { generateOrderId } = await getSignUtils() + return generateOrderId(chainId, order, params) + } + /** * Get the domain separator hash for the EIP-712 typed domain data being used for signing. * @param chainId {SupportedChainId} chainId The CoW Protocol protocol `chainId` context that's being used. diff --git a/src/order-signing/utils.ts b/src/order-signing/utils.ts index 18f33fd6..0cb980c3 100644 --- a/src/order-signing/utils.ts +++ b/src/order-signing/utils.ts @@ -3,12 +3,16 @@ import type { Signature, TypedDataDomain, EcdsaSigningScheme as EcdsaSigningSchemeContract, + Order, + OrderUidParams, } from '@cowprotocol/contracts' import { domain as domainGp, EcdsaSignature, IntChainIdTypedDataV4Signer, SigningScheme, + hashOrder, + packOrderUidParams, signOrder as signOrderGp, signOrderCancellation as signOrderCancellationGp, signOrderCancellations as signOrderCancellationsGp, @@ -230,3 +234,27 @@ export function getDomain(chainId: SupportedChainId): TypedDataDomain { return domainGp(chainId, settlementContract) } + +/** + * Generate a deterministic order ID for the specified order. + * @param {SupportedChainId} chainId The chain Id + * @param {Order} order order to sign + * @param {Pick} params order unique identifier parameters. + */ +export async function generateOrderId( + chainId: SupportedChainId, + order: Order, + params: Pick +): Promise<{ orderId: string; orderDigest: string }> { + const domain = await getDomain(chainId) + // Different validTo when signing because EthFlow contract expects it to be max for all orders + const orderDigest = hashOrder(domain, order) + // Generate the orderId from owner, orderDigest, and max validTo + const orderId = packOrderUidParams({ + ...params, + orderDigest, + validTo: order.validTo, + }) + + return { orderId, orderDigest } +} diff --git a/src/trading/calculateUniqueOrderId.ts b/src/trading/calculateUniqueOrderId.ts new file mode 100644 index 00000000..f4d4cdc6 --- /dev/null +++ b/src/trading/calculateUniqueOrderId.ts @@ -0,0 +1,48 @@ +import { OrderSigningUtils, UnsignedOrder } from '../order-signing' +import { ETH_FLOW_ADDRESSES, MAX_VALID_TO_EPOCH, SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' +import type { Order } from '@cowprotocol/contracts' + +export interface EthFlowOrderExistsCallback { + (orderId: string, orderDigest: string): Promise +} + +export async function calculateUniqueOrderId( + chainId: SupportedChainId, + order: UnsignedOrder, + checkEthFlowOrderExists?: EthFlowOrderExistsCallback +): Promise { + const { orderDigest, orderId } = await OrderSigningUtils.generateOrderId( + chainId, + { + ...order, + validTo: MAX_VALID_TO_EPOCH, + sellToken: WRAPPED_NATIVE_CURRENCIES[chainId], + } as Order, + { + owner: ETH_FLOW_ADDRESSES[chainId], + } + ) + + if (checkEthFlowOrderExists && (await checkEthFlowOrderExists(orderId, orderDigest))) { + console.error('ETH FLOW', '[calculateUniqueOrderId] ❌ Collision detected: ' + orderId, { + sellAmount: order.sellAmount, + fee: order.feeAmount, + }) + + // Recursive call, increment one fee until we get an unique order Id + return calculateUniqueOrderId(chainId, adjustAmounts(order), checkEthFlowOrderExists) + } + + return orderId +} + +function adjustAmounts(order: UnsignedOrder): UnsignedOrder { + const buyAmount = BigInt(order.buyAmount) + + // On fee=0, fee is, well, 0. Thus, we cannot shift amounts around and remain with the exact same price. + // Also, we don't want to touch the sell amount. + // If we move it down, the price might become "too good", if we move it up, the user might not have enough funds! + // Thus, we make the buy amount a tad bit worse by 1 wei. + // We can only hope this doesn't happen for an order buying 0 a decimals token 🤞 + return { ...order, buyAmount: (buyAmount - BigInt(1)).toString() } +} From 9c23fae37e454ed13349d77f588fe28b988e4acd Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 7 Nov 2024 12:20:59 +0500 Subject: [PATCH 12/67] feat: support on-chain trades --- abi/EthFlow.json | 152 ++++++++++++++++++++++++++++ src/common/consts.ts | 2 +- src/order-book/api.spec.ts | 8 +- src/order-book/transformOrder.ts | 4 +- src/trading/consts.ts | 3 + src/trading/getQuote.ts | 5 +- src/trading/postCoWProtocolTrade.ts | 14 ++- src/trading/postOnChainTrade.ts | 70 +++++++++++++ src/trading/types.ts | 2 +- 9 files changed, 248 insertions(+), 12 deletions(-) create mode 100644 abi/EthFlow.json create mode 100644 src/trading/postOnChainTrade.ts diff --git a/abi/EthFlow.json b/abi/EthFlow.json new file mode 100644 index 00000000..2e76a24b --- /dev/null +++ b/abi/EthFlow.json @@ -0,0 +1,152 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "contract IERC20", + "name": "buyToken", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sellAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "buyAmount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "appData", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "validTo", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "partiallyFillable", + "type": "bool" + }, + { + "internalType": "int64", + "name": "quoteId", + "type": "int64" + } + ], + "internalType": "struct EthFlowOrder.Data", + "name": "order", + "type": "tuple" + } + ], + "name": "createOrder", + "outputs": [ + { + "internalType": "bytes32", + "name": "orderHash", + "type": "bytes32" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "contract IERC20", + "name": "buyToken", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sellAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "buyAmount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "appData", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "validTo", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "partiallyFillable", + "type": "bool" + }, + { + "internalType": "int64", + "name": "quoteId", + "type": "int64" + } + ], + "internalType": "struct EthFlowOrder.Data", + "name": "order", + "type": "tuple" + } + ], + "name": "invalidateOrder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "orders", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint32", + "name": "validTo", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/common/consts.ts b/src/common/consts.ts index 268ba3b7..ed4d2f47 100644 --- a/src/common/consts.ts +++ b/src/common/consts.ts @@ -1,6 +1,6 @@ import { SupportedChainId } from './chains' -export const BUY_ETH_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' +export const ETH_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' export const EXTENSIBLE_FALLBACK_HANDLER = '0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5' export const COMPOSABLE_COW = '0xfdaFc9d1902f4e0b84f65F49f244b32b31013b74' diff --git a/src/order-book/api.spec.ts b/src/order-book/api.spec.ts index e9beaf59..2122a16e 100644 --- a/src/order-book/api.spec.ts +++ b/src/order-book/api.spec.ts @@ -15,7 +15,7 @@ import { CowError } from '../common/cow-error' import { OrderBookApi } from './api' import { BuyTokenDestination, EcdsaSigningScheme, OrderKind, SellTokenSource, SigningScheme } from './generated' import { SupportedChainId } from '../common/chains' -import { BUY_ETH_ADDRESS } from '../common/consts' +import { ETH_ADDRESS } from '../common/consts' import { AUCTION } from './mock' enableFetchMocks() @@ -534,7 +534,7 @@ describe('CoW Api', () => { // then expect(order?.owner).toEqual(order?.onchainUser) expect(order?.validTo).toEqual(order?.ethflowData?.userValidTo) - expect(order?.sellToken).toEqual(BUY_ETH_ADDRESS) + expect(order?.sellToken).toEqual(ETH_ADDRESS) }) test('getOrders', async () => { @@ -553,7 +553,7 @@ describe('CoW Api', () => { // eth flow order expect(orders[0].owner).toEqual(orders[0].onchainUser) expect(orders[0].validTo).toEqual(orders[0].ethflowData?.userValidTo) - expect(orders[0].sellToken).toEqual(BUY_ETH_ADDRESS) + expect(orders[0].sellToken).toEqual(ETH_ADDRESS) // regular order expect(orders[1].owner).toEqual(ORDER_RESPONSE.owner) expect(orders[1].validTo).toEqual(ORDER_RESPONSE.validTo) @@ -573,7 +573,7 @@ describe('CoW Api', () => { // eth flow order expect(txOrders[0].owner).toEqual(txOrders[0].onchainUser) expect(txOrders[0].validTo).toEqual(txOrders[0].ethflowData?.userValidTo) - expect(txOrders[0].sellToken).toEqual(BUY_ETH_ADDRESS) + expect(txOrders[0].sellToken).toEqual(ETH_ADDRESS) // regular order expect(txOrders[1].owner).toEqual(ORDER_RESPONSE.owner) expect(txOrders[1].validTo).toEqual(ORDER_RESPONSE.validTo) diff --git a/src/order-book/transformOrder.ts b/src/order-book/transformOrder.ts index cbc7d298..e1c8b6a8 100644 --- a/src/order-book/transformOrder.ts +++ b/src/order-book/transformOrder.ts @@ -1,4 +1,4 @@ -import { BUY_ETH_ADDRESS } from '../common/consts' +import { ETH_ADDRESS } from '../common/consts' import { Order } from './generated' import { EnrichedOrder } from './types' @@ -58,7 +58,7 @@ function transformEthFlowOrder(order: EnrichedOrder): EnrichedOrder { const { userValidTo: validTo } = ethflowData const owner = order.onchainUser || order.owner - const sellToken = BUY_ETH_ADDRESS + const sellToken = ETH_ADDRESS return { ...order, validTo, owner, sellToken } } diff --git a/src/trading/consts.ts b/src/trading/consts.ts index d3c69f3f..0d91d0c3 100644 --- a/src/trading/consts.ts +++ b/src/trading/consts.ts @@ -8,3 +8,6 @@ export const SIGN_SCHEME_MAP = { [EcdsaSigningScheme.EIP712]: SigningScheme.EIP712, [EcdsaSigningScheme.ETHSIGN]: SigningScheme.ETHSIGN, } + +// Use a 150K gas as a fallback if there's issue calculating the gas estimation (fixes some issues with some nodes failing to calculate gas costs for SC wallets) +export const GAS_LIMIT_DEFAULT = BigInt(150000) diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index ae411486..7e4abcb7 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -1,6 +1,6 @@ import { AppDataInfo, SwapAdvancedSettings, SwapParameters } from './types' import { DEFAULT_QUOTE_VALIDITY, log } from './consts' -import { ethers } from 'ethers' + import { getQuoteAmountsAndCosts, OrderBookApi, @@ -16,6 +16,7 @@ import { buildAppData } from './appDataUtils' import { UnsignedOrder } from '../order-signing' import { getOrderToSign } from './getOrderToSign' import { swapParamsToLimitOrderParams } from './utils' +import { ethers, Signer } from 'ethers' export interface QuoteResults { swapParameters: SwapParameters @@ -24,7 +25,7 @@ export interface QuoteResults { quoteResponse: OrderQuoteResponse appDataInfo: AppDataInfo orderBookApi: OrderBookApi - signer: ethers.Signer + signer: Signer } export async function getQuote( diff --git a/src/trading/postCoWProtocolTrade.ts b/src/trading/postCoWProtocolTrade.ts index 674dd2dc..89f3f152 100644 --- a/src/trading/postCoWProtocolTrade.ts +++ b/src/trading/postCoWProtocolTrade.ts @@ -1,17 +1,27 @@ import { OrderBookApi, OrderCreation } from '../order-book' -import { ethers } from 'ethers' +import type { Signer } from 'ethers' import { AppDataInfo, LimitOrderParameters } from './types' import { log, SIGN_SCHEME_MAP } from './consts' import { OrderSigningUtils } from '../order-signing' import { getOrderToSign } from './getOrderToSign' +import { ETH_ADDRESS } from '../common' +import { postOnChainTrade } from './postOnChainTrade' export async function postCoWProtocolTrade( orderBookApi: OrderBookApi, - signer: ethers.Signer, + signer: Signer, appData: AppDataInfo, params: LimitOrderParameters, networkCostsAmount = '0' ): Promise { + const isEthFlowOrder = params.sellToken.toLowerCase() === ETH_ADDRESS.toLowerCase() + + if (isEthFlowOrder) { + const { orderId } = await postOnChainTrade(signer, appData, params, networkCostsAmount) + + return orderId + } + const { chainId, quoteId = null } = params const { appDataKeccak256, fullAppData } = appData diff --git a/src/trading/postOnChainTrade.ts b/src/trading/postOnChainTrade.ts new file mode 100644 index 00000000..9c2808a3 --- /dev/null +++ b/src/trading/postOnChainTrade.ts @@ -0,0 +1,70 @@ +import { Signer } from 'ethers' +import { AppDataInfo, LimitOrderParameters } from './types' +import { calculateUniqueOrderId, EthFlowOrderExistsCallback } from './calculateUniqueOrderId' +import { getOrderToSign } from './getOrderToSign' +import { type EthFlow, EthFlow__factory } from '../common/generated' +import { ETH_FLOW_ADDRESSES, SupportedChainId } from '../common' +import { GAS_LIMIT_DEFAULT } from './consts' +import type { EthFlowOrder } from '../common/generated/EthFlow' + +export async function postOnChainTrade( + signer: Signer, + appData: AppDataInfo, + params: LimitOrderParameters, + networkCostsAmount = '0', + checkEthFlowOrderExists?: EthFlowOrderExistsCallback +): Promise<{ txHash: string; orderId: string }> { + const { chainId, quoteId } = params + const { fullAppData } = appData + + const from = await signer.getAddress() + + const contract = getEthFlowContract(chainId, signer) + const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appData) + const orderId = await calculateUniqueOrderId(chainId, orderToSign, checkEthFlowOrderExists) + + const ethOrderParams: EthFlowOrder.DataStruct = { + ...orderToSign, + quoteId, + appData: fullAppData, + validTo: orderToSign.validTo.toString(), + } + + const estimatedGas = await contract.estimateGas + .createOrder(ethOrderParams, { value: orderToSign.sellAmount }) + .then((res) => BigInt(res.toHexString())) + .catch((error) => { + console.error(error) + + return GAS_LIMIT_DEFAULT + }) + + const txReceipt = await contract.createOrder(ethOrderParams, { + value: orderToSign.sellAmount, + gasLimit: calculateGasMargin(estimatedGas), + }) + + return { txHash: txReceipt.hash, orderId } +} + +const ethFlowContractCache: Partial> = {} + +function getEthFlowContract(chainId: SupportedChainId, signer: Signer): EthFlow { + const cache = ethFlowContractCache[chainId] + + if (cache) return cache + + const contract = EthFlow__factory.connect(ETH_FLOW_ADDRESSES[chainId], signer) + + ethFlowContractCache[chainId] = contract + + return contract +} + +/** + * Returns the gas value plus a margin for unexpected or variable gas costs (20%) + * @param value the gas value to pad + */ +function calculateGasMargin(value: bigint): bigint { + return value + (value * BigInt(20)) / BigInt(100) +} diff --git a/src/trading/types.ts b/src/trading/types.ts index e96457b9..c5e6e173 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -35,8 +35,8 @@ export interface SwapParameters extends TraderParameters, TradeParameters {} export interface LimitTradeParameters extends Omit { sellAmount: string buyAmount: string + quoteId: number validTo?: number - quoteId?: number } export interface LimitOrderParameters extends TraderParameters, LimitTradeParameters {} From 6fcff584c3be9a684c981b566bfcc513a1aa3c57 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 7 Nov 2024 12:24:08 +0500 Subject: [PATCH 13/67] chore: reduce getOrderToSign parameters --- src/trading/getOrderToSign.ts | 5 ++--- src/trading/getQuote.ts | 2 +- src/trading/postCoWProtocolTrade.ts | 2 +- src/trading/postOnChainTrade.ts | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/trading/getOrderToSign.ts b/src/trading/getOrderToSign.ts index d7844912..646e5633 100644 --- a/src/trading/getOrderToSign.ts +++ b/src/trading/getOrderToSign.ts @@ -1,6 +1,6 @@ import { getQuoteAmountsAndCosts, type OrderParameters } from '../order-book' import { UnsignedOrder } from '../order-signing' -import { AppDataInfo, LimitOrderParameters } from './types' +import { LimitOrderParameters } from './types' import { DEFAULT_QUOTE_VALIDITY } from './consts' interface OrderToSignParams { @@ -11,7 +11,7 @@ interface OrderToSignParams { export function getOrderToSign( { from, networkCostsAmount = '0' }: OrderToSignParams, limitOrderParams: LimitOrderParameters, - appData: AppDataInfo + appDataKeccak256: string ): UnsignedOrder { const { sellAmount, @@ -29,7 +29,6 @@ export function getOrderToSign( const receiver = limitOrderParams.receiver || from const validTo = limitOrderParams.validTo || Math.floor(Date.now() / 1000) + (validFor || DEFAULT_QUOTE_VALIDITY) - const { appDataKeccak256 } = appData const orderParams: OrderParameters = { sellToken, diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index 7e4abcb7..041ca8a7 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -101,7 +101,7 @@ export async function getQuote( const orderToSign = getOrderToSign( { from, networkCostsAmount: quoteResponse.quote.feeAmount }, swapParamsToLimitOrderParams(swapParameters, quoteResponse), - appDataInfo + appDataInfo.appDataKeccak256 ) return { amountsAndCosts, quoteResponse, appDataInfo, orderBookApi, signer, orderToSign, swapParameters } diff --git a/src/trading/postCoWProtocolTrade.ts b/src/trading/postCoWProtocolTrade.ts index 89f3f152..a5141821 100644 --- a/src/trading/postCoWProtocolTrade.ts +++ b/src/trading/postCoWProtocolTrade.ts @@ -27,7 +27,7 @@ export async function postCoWProtocolTrade( const from = await signer.getAddress() - const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appData) + const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appData.appDataKeccak256) log('Signing order...') diff --git a/src/trading/postOnChainTrade.ts b/src/trading/postOnChainTrade.ts index 9c2808a3..175ff457 100644 --- a/src/trading/postOnChainTrade.ts +++ b/src/trading/postOnChainTrade.ts @@ -20,7 +20,7 @@ export async function postOnChainTrade( const from = await signer.getAddress() const contract = getEthFlowContract(chainId, signer) - const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appData) + const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appData.appDataKeccak256) const orderId = await calculateUniqueOrderId(chainId, orderToSign, checkEthFlowOrderExists) const ethOrderParams: EthFlowOrder.DataStruct = { From 4a1f35e99837b4adf4f61c3a8254ef836f0b8f6e Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 7 Nov 2024 14:53:42 +0500 Subject: [PATCH 14/67] feat: support on-chain orders --- examples/vanilla/src/formState.ts | 4 +++- examples/vanilla/src/index.ts | 2 +- examples/vanilla/src/pageActions.ts | 17 +++++++++++++++++ examples/vanilla/src/pageHtml.ts | 3 +++ examples/vanilla/src/tokens.ts | 12 +++++++++++- package.json | 4 ++-- src/common/consts.ts | 2 ++ src/cow-shed/CoWShedHooks.ts | 2 +- src/cow-shed/contracts.ts | 6 +++--- src/trading/calculateUniqueOrderId.ts | 4 +++- src/trading/getQuote.ts | 12 ++++++------ src/trading/postCoWProtocolTrade.ts | 8 +++----- src/trading/postLimitOrder.ts | 4 ++-- src/trading/postOnChainTrade.ts | 16 ++++++++++++---- src/trading/types.ts | 3 ++- src/trading/utils.ts | 27 ++++++++++++++++++++++++--- 16 files changed, 95 insertions(+), 31 deletions(-) diff --git a/examples/vanilla/src/formState.ts b/examples/vanilla/src/formState.ts index 9fd9a839..9a669c28 100644 --- a/examples/vanilla/src/formState.ts +++ b/examples/vanilla/src/formState.ts @@ -29,7 +29,9 @@ export const getTradeParameters = (): TradeParameters => { const isSell = kind === 'sell' const sellToken = TOKENS[chainId].find((t) => t.address === _sellToken) const buyToken = TOKENS[chainId].find((t) => t.address === _buyToken) - const amount = BigInt(_amount) * BigInt(10 ** (isSell ? sellToken.decimals : buyToken.decimals)) + const decimals = isSell ? sellToken.decimals : buyToken.decimals + const multiplicator = decimals > 3 ? 3 : 0 + const amount = BigInt(+_amount * 10 ** multiplicator) * BigInt(10 ** (decimals - multiplicator)) const slippageBps = _slippageBps ? +_slippageBps : undefined return { diff --git a/examples/vanilla/src/index.ts b/examples/vanilla/src/index.ts index de9bbb00..e8fa0cc5 100644 --- a/examples/vanilla/src/index.ts +++ b/examples/vanilla/src/index.ts @@ -42,7 +42,7 @@ const appCode = 'trade-sdk-example' const sdk = new TradingSdk({ chainId, - signer: privateKey, + signer: privateKey || (window as any).ethereum, appCode, }) diff --git a/examples/vanilla/src/pageActions.ts b/examples/vanilla/src/pageActions.ts index 4329ffc2..f8e0b5bf 100644 --- a/examples/vanilla/src/pageActions.ts +++ b/examples/vanilla/src/pageActions.ts @@ -43,6 +43,23 @@ function onNetworkChange() { } function onGetQuote(actions: Actions) { + const connectWallet = document.getElementById('connectWallet') as HTMLButtonElement + + connectWallet.addEventListener('click', async (event) => { + event.preventDefault() + + try { + const accounts: string[] = await (window as any).ethereum.request({ method: 'eth_requestAccounts' }) + + if (accounts.length) { + connectWallet.disabled = true + connectWallet.innerText = 'Connected' + } + } catch (error) { + printError(error) + } + }) + document.getElementById('getQuote').addEventListener('click', (event) => { event.preventDefault() diff --git a/examples/vanilla/src/pageHtml.ts b/examples/vanilla/src/pageHtml.ts index 94d50db5..868712f0 100644 --- a/examples/vanilla/src/pageHtml.ts +++ b/examples/vanilla/src/pageHtml.ts @@ -26,6 +26,9 @@ export function pageHtml() {
+
+ or +
diff --git a/examples/vanilla/src/tokens.ts b/examples/vanilla/src/tokens.ts index 75c0b6ad..acf489bc 100644 --- a/examples/vanilla/src/tokens.ts +++ b/examples/vanilla/src/tokens.ts @@ -1,4 +1,4 @@ -import { SupportedChainId } from '../../../src' +import { ETH_ADDRESS, SupportedChainId } from '../../../src' class Token { constructor( @@ -12,12 +12,14 @@ class Token { export const TOKENS: Record = { [SupportedChainId.MAINNET]: [ + new Token(SupportedChainId.MAINNET, ETH_ADDRESS, 18, 'ETH', 'Ether'), new Token(SupportedChainId.MAINNET, '0xdAC17F958D2ee523a2206206994597C13D831ec7', 6, 'USDT', 'Tether USD'), new Token(SupportedChainId.MAINNET, '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 8, 'WBTC', 'Wrapped BTC'), new Token(SupportedChainId.MAINNET, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD Coin'), new Token(SupportedChainId.MAINNET, '0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB', 18, 'COW', 'CoW Protocol Token'), ], [SupportedChainId.GNOSIS_CHAIN]: [ + new Token(SupportedChainId.MAINNET, ETH_ADDRESS, 18, 'xDAI', 'xDAI'), new Token(SupportedChainId.GNOSIS_CHAIN, '0x4ECaBa5870353805a9F068101A40E0f32ed605C6', 6, 'USDT', 'Tether USD'), new Token(SupportedChainId.GNOSIS_CHAIN, '0x8e5bbbb09ed1ebde8674cda39a0c169401db4252', 8, 'WBTC', 'Wrapped BTC'), new Token(SupportedChainId.GNOSIS_CHAIN, '0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83', 6, 'USDC', 'USD Coin'), @@ -30,6 +32,7 @@ export const TOKENS: Record = { ), ], [SupportedChainId.ARBITRUM_ONE]: [ + new Token(SupportedChainId.ARBITRUM_ONE, ETH_ADDRESS, 18, 'ETH', 'Ether'), new Token(SupportedChainId.ARBITRUM_ONE, '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', 6, 'USDT', 'Tether USD'), new Token(SupportedChainId.ARBITRUM_ONE, '0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f', 8, 'WBTC', 'Wrapped BTC'), new Token(SupportedChainId.ARBITRUM_ONE, '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', 6, 'USDC', 'USD Coin'), @@ -42,9 +45,16 @@ export const TOKENS: Record = { ), ], [SupportedChainId.SEPOLIA]: [ + new Token(SupportedChainId.SEPOLIA, ETH_ADDRESS, 18, 'ETH', 'Ether'), new Token(SupportedChainId.SEPOLIA, '0x58eb19ef91e8a6327fed391b51ae1887b833cc91', 6, 'USDT', 'Tether USD'), new Token(SupportedChainId.SEPOLIA, '0xd3f3d46FeBCD4CdAa2B83799b7A5CdcB69d135De', 18, 'GNO', 'GNO (test)'), new Token(SupportedChainId.SEPOLIA, '0xbe72E441BF55620febc26715db68d3494213D8Cb', 18, 'USDC', 'USDC (test)'), new Token(SupportedChainId.SEPOLIA, '0x0625aFB445C3B6B7B929342a04A22599fd5dBB59', 18, 'COW', 'CoW Protocol Token'), ], + [SupportedChainId.BASE]: [ + new Token(SupportedChainId.BASE, ETH_ADDRESS, 18, 'ETH', 'Ether'), + new Token(SupportedChainId.BASE, '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2', 6, 'USDT', 'Tether USD'), + new Token(SupportedChainId.BASE, '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', 6, 'USDC', 'USD Coin'), + new Token(SupportedChainId.BASE, '0x60a3e35cc302bfa44cb288bc5a4f316fdb1adb42', 6, 'EURC', 'EURC'), + ], } diff --git a/package.json b/package.json index b6505987..78baff7d 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "prepare": "npm run build", "prepublishOnly": "npm test && npm run lint", "graphql:codegen": "graphql-codegen --config graphql-codegen.yml", - "swagger:codegen": " openapi --input https://raw.githubusercontent.com/cowprotocol/services/v2.281.0/crates/orderbook/openapi.yml --output src/order-book/generated --exportServices false --exportCore false", + "swagger:codegen": " openapi --input https://raw.githubusercontent.com/cowprotocol/services/main/crates/orderbook/openapi.yml --output src/order-book/generated --exportServices false --exportCore false", "typechain:codegen": "typechain --target ethers-v5 --out-dir ./src/common/generated './abi/*.json'" }, "dependencies": { @@ -101,4 +101,4 @@ "typescript", "subgraph" ] -} \ No newline at end of file +} diff --git a/src/common/consts.ts b/src/common/consts.ts index ed4d2f47..e3790e14 100644 --- a/src/common/consts.ts +++ b/src/common/consts.ts @@ -61,6 +61,7 @@ export const WRAPPED_NATIVE_CURRENCIES: Record = { [SupportedChainId.GNOSIS_CHAIN]: '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d', [SupportedChainId.ARBITRUM_ONE]: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', [SupportedChainId.SEPOLIA]: '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14', + [SupportedChainId.BASE]: '0x4200000000000000000000000000000000000006', } /** @@ -71,6 +72,7 @@ export const ETH_FLOW_ADDRESSES: Record = { [SupportedChainId.GNOSIS_CHAIN]: '0x40A50cf069e992AA4536211B23F286eF88752187', [SupportedChainId.ARBITRUM_ONE]: '0x552fcecc218158fff20e505c8f3ad24f8e1dd33c', [SupportedChainId.SEPOLIA]: '0x0b7795E18767259CC253a2dF471db34c72B49516', + [SupportedChainId.BASE]: 'TODO', // TODO } // const BARN_ETH_FLOW_ADDRESSES: Record = { diff --git a/src/cow-shed/CoWShedHooks.ts b/src/cow-shed/CoWShedHooks.ts index 07bb5c0a..61dcf65d 100644 --- a/src/cow-shed/CoWShedHooks.ts +++ b/src/cow-shed/CoWShedHooks.ts @@ -6,7 +6,7 @@ import { solidityKeccak256, splitSignature, } from 'ethers/lib/utils' -import { COW_SHED_FACTORY, COW_SHED_IMPLEMENTATION, SupportedChainId } from 'src/common' +import { COW_SHED_FACTORY, COW_SHED_IMPLEMENTATION, SupportedChainId } from '../common' import { COW_SHED_712_TYPES, ICoWShedCall, ICoWShedOptions } from './types' import { COW_SHED_PROXY_INIT_CODE } from './proxyInitCode' import type { Signer } from '@ethersproject/abstract-signer' diff --git a/src/cow-shed/contracts.ts b/src/cow-shed/contracts.ts index 3f2437bc..b07cabc5 100644 --- a/src/cow-shed/contracts.ts +++ b/src/cow-shed/contracts.ts @@ -1,6 +1,6 @@ -import { CoWShedInterface } from 'src/common/generated/CoWShed' -import { CoWShed__factory, CoWShedFactory__factory } from 'src/common/generated' -import { CoWShedFactoryInterface } from 'src/common/generated/CoWShedFactory' +import { CoWShedInterface } from '../common/generated/CoWShed' +import { CoWShed__factory, CoWShedFactory__factory } from '../common/generated' +import { CoWShedFactoryInterface } from '../common/generated/CoWShedFactory' let cowShedInterfaceCache: CoWShedInterface | undefined let cowShedFactoryInterface: CoWShedFactoryInterface | undefined diff --git a/src/trading/calculateUniqueOrderId.ts b/src/trading/calculateUniqueOrderId.ts index f4d4cdc6..5d7e4a8e 100644 --- a/src/trading/calculateUniqueOrderId.ts +++ b/src/trading/calculateUniqueOrderId.ts @@ -1,6 +1,6 @@ import { OrderSigningUtils, UnsignedOrder } from '../order-signing' import { ETH_FLOW_ADDRESSES, MAX_VALID_TO_EPOCH, SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' -import type { Order } from '@cowprotocol/contracts' +import type { Order, OrderBalance } from '@cowprotocol/contracts' export interface EthFlowOrderExistsCallback { (orderId: string, orderDigest: string): Promise @@ -15,6 +15,8 @@ export async function calculateUniqueOrderId( chainId, { ...order, + sellTokenBalance: order.sellTokenBalance as string as OrderBalance, + buyTokenBalance: order.buyTokenBalance as string as OrderBalance, validTo: MAX_VALID_TO_EPOCH, sellToken: WRAPPED_NATIVE_CURRENCIES[chainId], } as Order, diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index 041ca8a7..8c1e1a2e 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -15,8 +15,9 @@ import { import { buildAppData } from './appDataUtils' import { UnsignedOrder } from '../order-signing' import { getOrderToSign } from './getOrderToSign' -import { swapParamsToLimitOrderParams } from './utils' -import { ethers, Signer } from 'ethers' +import { getIsEthFlowOrder, getSigner, swapParamsToLimitOrderParams } from './utils' +import { Signer } from 'ethers' +import { WRAPPED_NATIVE_CURRENCIES } from '../common' export interface QuoteResults { swapParameters: SwapParameters @@ -49,8 +50,7 @@ export async function getQuote( log(`Swap ${amount} ${sellToken} for ${buyToken} on chain ${chainId}`) - const signer = - typeof swapParameters.signer === 'string' ? new ethers.Wallet(swapParameters.signer) : swapParameters.signer + const signer = getSigner(swapParameters.signer) const orderBookApi = new OrderBookApi({ chainId, env }) const from = await signer.getAddress() @@ -72,13 +72,13 @@ export async function getQuote( const quoteRequest: OrderQuoteRequest = { from, - sellToken, + sellToken: getIsEthFlowOrder(swapParameters) ? WRAPPED_NATIVE_CURRENCIES[chainId] : sellToken, buyToken, receiver, validFor, appData: fullAppData, appDataHash: appDataKeccak256, - priceQuality: PriceQuality.OPTIMAL, + priceQuality: PriceQuality.OPTIMAL, // Do not change this parameter because we rely on the fact that quote has id signingScheme: SigningScheme.EIP712, ...(isSell ? { kind: OrderQuoteSideKindSell.SELL, sellAmountBeforeFee: amount } diff --git a/src/trading/postCoWProtocolTrade.ts b/src/trading/postCoWProtocolTrade.ts index a5141821..5f4b59bd 100644 --- a/src/trading/postCoWProtocolTrade.ts +++ b/src/trading/postCoWProtocolTrade.ts @@ -4,8 +4,8 @@ import { AppDataInfo, LimitOrderParameters } from './types' import { log, SIGN_SCHEME_MAP } from './consts' import { OrderSigningUtils } from '../order-signing' import { getOrderToSign } from './getOrderToSign' -import { ETH_ADDRESS } from '../common' import { postOnChainTrade } from './postOnChainTrade' +import { getIsEthFlowOrder } from './utils' export async function postCoWProtocolTrade( orderBookApi: OrderBookApi, @@ -14,10 +14,8 @@ export async function postCoWProtocolTrade( params: LimitOrderParameters, networkCostsAmount = '0' ): Promise { - const isEthFlowOrder = params.sellToken.toLowerCase() === ETH_ADDRESS.toLowerCase() - - if (isEthFlowOrder) { - const { orderId } = await postOnChainTrade(signer, appData, params, networkCostsAmount) + if (getIsEthFlowOrder(params)) { + const { orderId } = await postOnChainTrade(orderBookApi, signer, appData, params, networkCostsAmount) return orderId } diff --git a/src/trading/postLimitOrder.ts b/src/trading/postLimitOrder.ts index 6e9b4d77..f3711d60 100644 --- a/src/trading/postLimitOrder.ts +++ b/src/trading/postLimitOrder.ts @@ -1,9 +1,9 @@ import { LimitOrderAdvancedSettings, LimitOrderParameters } from './types' import { log } from './consts' -import { ethers } from 'ethers' import { OrderBookApi } from '../order-book' import { buildAppData } from './appDataUtils' import { postCoWProtocolTrade } from './postCoWProtocolTrade' +import { getSigner } from './utils' export async function postLimitOrder(params: LimitOrderParameters, advancedSettings?: LimitOrderAdvancedSettings) { const { @@ -20,7 +20,7 @@ export async function postLimitOrder(params: LimitOrderParameters, advancedSetti log(`Limit order ${sellAmount} ${sellToken} for ${buyAmount} ${buyToken} on chain ${chainId}`) - const signer = typeof params.signer === 'string' ? new ethers.Wallet(params.signer) : params.signer + const signer = getSigner(params.signer) const orderBookApi = new OrderBookApi({ chainId, env }) log('Building app data...') diff --git a/src/trading/postOnChainTrade.ts b/src/trading/postOnChainTrade.ts index 175ff457..60f0c839 100644 --- a/src/trading/postOnChainTrade.ts +++ b/src/trading/postOnChainTrade.ts @@ -4,10 +4,12 @@ import { calculateUniqueOrderId, EthFlowOrderExistsCallback } from './calculateU import { getOrderToSign } from './getOrderToSign' import { type EthFlow, EthFlow__factory } from '../common/generated' import { ETH_FLOW_ADDRESSES, SupportedChainId } from '../common' -import { GAS_LIMIT_DEFAULT } from './consts' +import { GAS_LIMIT_DEFAULT, log } from './consts' import type { EthFlowOrder } from '../common/generated/EthFlow' +import { OrderBookApi } from '../order-book' export async function postOnChainTrade( + orderBookApi: OrderBookApi, signer: Signer, appData: AppDataInfo, params: LimitOrderParameters, @@ -15,21 +17,25 @@ export async function postOnChainTrade( checkEthFlowOrderExists?: EthFlowOrderExistsCallback ): Promise<{ txHash: string; orderId: string }> { const { chainId, quoteId } = params - const { fullAppData } = appData + const { appDataKeccak256, fullAppData } = appData const from = await signer.getAddress() const contract = getEthFlowContract(chainId, signer) - const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appData.appDataKeccak256) + const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appDataKeccak256) const orderId = await calculateUniqueOrderId(chainId, orderToSign, checkEthFlowOrderExists) const ethOrderParams: EthFlowOrder.DataStruct = { ...orderToSign, quoteId, - appData: fullAppData, + appData: appDataKeccak256, validTo: orderToSign.validTo.toString(), } + log('Uploading app-data') + await orderBookApi.uploadAppData(appDataKeccak256, fullAppData) + + log('Estimating on-chain order gas') const estimatedGas = await contract.estimateGas .createOrder(ethOrderParams, { value: orderToSign.sellAmount }) .then((res) => BigInt(res.toHexString())) @@ -39,11 +45,13 @@ export async function postOnChainTrade( return GAS_LIMIT_DEFAULT }) + log('Sending on-chain order transaction') const txReceipt = await contract.createOrder(ethOrderParams, { value: orderToSign.sellAmount, gasLimit: calculateGasMargin(estimatedGas), }) + log(`On-chain order transaction sent, txHash: ${txReceipt.hash}, order: ${orderId}`) return { txHash: txReceipt.hash, orderId } } diff --git a/src/trading/types.ts b/src/trading/types.ts index c5e6e173..a577a1de 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -3,6 +3,7 @@ import { Address, OrderQuoteRequest, OrderKind } from '../order-book' import type { Signer } from '@ethersproject/abstract-signer' import { CowEnv, SupportedChainId } from '../common' import { QuoteResults } from './getQuote' +import type { ExternalProvider } from '@ethersproject/providers' export interface TradeBaseParameters { kind: OrderKind @@ -24,7 +25,7 @@ export interface TradeOptionalParameters { export interface TraderParameters { chainId: SupportedChainId - signer: Signer | string + signer: Signer | ExternalProvider | string appCode: string } diff --git a/src/trading/utils.ts b/src/trading/utils.ts index d7eeae2a..8ca9f9f0 100644 --- a/src/trading/utils.ts +++ b/src/trading/utils.ts @@ -1,9 +1,30 @@ -import { LimitOrderParameters, SwapParameters } from './types' +import { LimitOrderParameters, SwapParameters, TraderParameters } from './types' import { OrderQuoteResponse } from '../order-book' +import { ETH_ADDRESS } from '../common' +import { ethers, Signer } from 'ethers' +import { Web3Provider } from '@ethersproject/providers' export function swapParamsToLimitOrderParams( params: SwapParameters, - { quote: { sellAmount, buyAmount } }: OrderQuoteResponse + { quote: { sellAmount, buyAmount }, id }: OrderQuoteResponse ): LimitOrderParameters { - return { ...params, sellAmount, buyAmount } + // In this SDK we always use Optimal quotes which are always have id + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return { ...params, sellAmount, buyAmount, quoteId: id! } +} + +export function getIsEthFlowOrder(params: { sellToken: string }): boolean { + return params.sellToken.toLowerCase() === ETH_ADDRESS.toLowerCase() +} + +export function getSigner(signer: TraderParameters['signer']): Signer { + if (typeof signer === 'string') return new ethers.Wallet(signer) + + if ('request' in signer || 'send' in signer) { + const provider = new Web3Provider(signer) + + return provider.getSigner() + } + + return signer as Signer } From 240ebfbe3a4a652fb4889d4a83f8abb85089fb6f Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 7 Nov 2024 17:04:23 +0500 Subject: [PATCH 15/67] test: app data utils --- src/trading/appDataUtils.test.ts | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/trading/appDataUtils.test.ts diff --git a/src/trading/appDataUtils.test.ts b/src/trading/appDataUtils.test.ts new file mode 100644 index 00000000..ae0edc69 --- /dev/null +++ b/src/trading/appDataUtils.test.ts @@ -0,0 +1,51 @@ +import { buildAppData, generateAppDataFromDoc } from './appDataUtils' + +describe('AppData utils', () => { + it('Should add all required parameters to the doc', async () => { + const data = await buildAppData({ + slippageBps: 100, + appCode: 'cowswap', + orderClass: 'market', + }) + const parsedData = JSON.parse(data.fullAppData) + + expect(parsedData.metadata.quote.slippageBips).toBe(100) + expect(parsedData.appCode).toBe('cowswap') + expect(parsedData.metadata.orderClass.orderClass).toBe('market') + }) + + it('Should add advanced parameters to the doc', async () => { + const data = await buildAppData( + { + slippageBps: 100, + appCode: 'cowswap', + orderClass: 'market', + }, + { + environment: 'staging', + metadata: { + partnerFee: { + bps: 66, + recipient: '0xccc', + }, + replacedOrder: { + uid: '0xaaa', + }, + }, + } + ) + const parsedData = JSON.parse(data.fullAppData) + + expect(parsedData.environment).toBe('staging') + expect(parsedData.metadata.partnerFee.bps).toBe(66) + expect(parsedData.metadata.partnerFee.recipient).toBe('0xccc') + expect(parsedData.metadata.replacedOrder.uid).toBe('0xaaa') + }) + + it('App data doc should be stringified in deterministic way', async () => { + const data1 = await generateAppDataFromDoc({ version: '1.0', appCode: 'code', metadata: {} }) + const data2 = await generateAppDataFromDoc({ appCode: 'code', metadata: {}, version: '1.0' }) + + expect(data1.fullAppData).toBe(data2.fullAppData) + }) +}) From a8d1ec96e1532652a109069c983ba5bb1e289fdf Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 7 Nov 2024 19:44:14 +0500 Subject: [PATCH 16/67] test: test calculateUniqueOrderId --- src/trading/calculateUniqueOrderId.test.ts | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/trading/calculateUniqueOrderId.test.ts diff --git a/src/trading/calculateUniqueOrderId.test.ts b/src/trading/calculateUniqueOrderId.test.ts new file mode 100644 index 00000000..1b22ea53 --- /dev/null +++ b/src/trading/calculateUniqueOrderId.test.ts @@ -0,0 +1,91 @@ +jest.mock('../order-signing', () => ({ + OrderSigningUtils: { + generateOrderId: jest.fn(), + }, +})) + +import { calculateUniqueOrderId } from './calculateUniqueOrderId' +import { MAX_VALID_TO_EPOCH, SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' +import { OrderSigningUtils as OrderSigningUtilsMock, UnsignedOrder } from '../order-signing' +import { BuyTokenDestination, OrderKind, SellTokenSource } from '../order-book/generated' + +const orderMock: UnsignedOrder = { + buyAmount: '100', + buyToken: '0xb', + buyTokenBalance: BuyTokenDestination.ERC20, + sellAmount: '30', + sellToken: '0xa', + sellTokenBalance: SellTokenSource.ERC20, + validTo: 10000033, + feeAmount: '0', + kind: OrderKind.BUY, + partiallyFillable: false, + receiver: '0x123', + appData: '0x0004', +} + +describe('calculateUniqueOrderId', () => { + let generateOrderId: jest.SpyInstance + + beforeAll(() => { + generateOrderId = OrderSigningUtilsMock.generateOrderId as unknown as jest.SpyInstance + }) + + beforeEach(() => { + generateOrderId.mockResolvedValue({ orderDigest: '0x000dd', orderId: '0xab444' }) + }) + + afterEach(() => { + generateOrderId.mockReset() + }) + + it('Should always set validTo to the maximum value', async () => { + await calculateUniqueOrderId(SupportedChainId.MAINNET, orderMock) + + const [chainId, order] = generateOrderId.mock.calls[0] + + expect(chainId).toBe(SupportedChainId.MAINNET) + expect(order.validTo).toBe(MAX_VALID_TO_EPOCH) + }) + it('Should always set sellToken to wrapped native token', async () => { + await calculateUniqueOrderId(SupportedChainId.MAINNET, orderMock) + + const [chainId, order] = generateOrderId.mock.calls[0] + + expect(chainId).toBe(SupportedChainId.MAINNET) + expect(order.sellToken).toBe(WRAPPED_NATIVE_CURRENCIES[SupportedChainId.MAINNET]) + }) + + describe('When checkEthFlowOrderExists is set', () => { + it('Then the callback should be called with the orderId and orderDigest', async () => { + const checkEthFlowOrderExists = jest.fn().mockResolvedValue(false) + await calculateUniqueOrderId(SupportedChainId.MAINNET, orderMock, checkEthFlowOrderExists) + + expect(checkEthFlowOrderExists).toHaveBeenCalledWith('0xab444', '0x000dd') + expect(checkEthFlowOrderExists).toHaveBeenCalledTimes(1) + }) + + describe('When checkEthFlowOrderExists returns true', () => { + it('Then it should call itself with the adjusted order', async () => { + let alreadyCalled = false + + const checkEthFlowOrderExists = jest.fn().mockImplementation(() => { + return Promise.resolve( + (() => { + if (alreadyCalled) return false + alreadyCalled = true + + return true + })() + ) + }) + await calculateUniqueOrderId(SupportedChainId.MAINNET, orderMock, checkEthFlowOrderExists) + + const [chainId, order] = generateOrderId.mock.calls[1] + + expect(chainId).toBe(SupportedChainId.MAINNET) + expect(order.buyAmount).toBe('99') + }) + }) + }) +}) From 59fd04b8d5829c9bfbfefdd2ce522ae8da04fd08 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 7 Nov 2024 20:02:40 +0500 Subject: [PATCH 17/67] test: test getOrderToSign --- src/trading/getOrderToSign.test.ts | 81 ++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/trading/getOrderToSign.test.ts diff --git a/src/trading/getOrderToSign.test.ts b/src/trading/getOrderToSign.test.ts new file mode 100644 index 00000000..1dd2f665 --- /dev/null +++ b/src/trading/getOrderToSign.test.ts @@ -0,0 +1,81 @@ +jest.mock('cross-fetch', () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fetchMock = require('jest-fetch-mock') + // Require the original module to not be mocked... + const originalFetch = jest.requireActual('cross-fetch') + return { + __esModule: true, + ...originalFetch, + default: fetchMock, + } +}) + +import { getOrderToSign } from './getOrderToSign' +import { LimitOrderParameters } from './types' +import { SupportedChainId } from '../common' +import { OrderKind } from '../order-book' +import { DEFAULT_QUOTE_VALIDITY } from './consts' + +const currentTimestamp = 1487076708000 + +const params = { from: '0xaaa444' } + +const defaultOrderParams: LimitOrderParameters = { + chainId: SupportedChainId.GNOSIS_CHAIN, + signer: '0x006', + appCode: '0x007', + sellToken: '0xaaa', + sellTokenDecimals: 18, + buyToken: '0xbbb', + buyTokenDecimals: 18, + sellAmount: '1000000000000000000', + buyAmount: '2000000000000000000', + kind: OrderKind.SELL, + quoteId: 31, + slippageBps: 50, +} + +const appDataKeccak256 = '0x00355666666' + +describe('getOrderToSign', () => { + beforeEach(() => { + Date.now = jest.fn(() => currentTimestamp) + }) + it('When receiver is not set, then should use "from" parameter instead', () => { + const result = getOrderToSign(params, { ...defaultOrderParams, receiver: undefined }, appDataKeccak256) + + expect(result.receiver).toBe('0xaaa444') + }) + + it('When validTo is not set, then should use "validFor" parameter instead', () => { + const result = getOrderToSign( + params, + { ...defaultOrderParams, validTo: undefined, validFor: 600 }, + appDataKeccak256 + ) + + expect(result.validTo).toBe(currentTimestamp / 1000 + 600) + }) + + it('When both validTo and validFor are not set, then should use default value', () => { + const result = getOrderToSign( + params, + { ...defaultOrderParams, validTo: undefined, validFor: undefined }, + appDataKeccak256 + ) + + expect(result.validTo).toBe(currentTimestamp / 1000 + DEFAULT_QUOTE_VALIDITY) + }) + + it('When sell order, then buy amount should be adjusted to slippage', () => { + const result = getOrderToSign(params, { ...defaultOrderParams, kind: OrderKind.SELL }, appDataKeccak256) + + expect(result.buyAmount).toBe('1990000000000000000') + }) + + it('When buy order, then sell amount should be adjusted to slippage', () => { + const result = getOrderToSign(params, { ...defaultOrderParams, kind: OrderKind.BUY }, appDataKeccak256) + + expect(result.sellAmount).toBe('1005000000000000000') + }) +}) From 6351ae7b61ab91725e9c97b625199616779cfe90 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 8 Nov 2024 14:43:53 +0500 Subject: [PATCH 18/67] test: test getQuote --- src/order-book/quoteAmountsAndCostsUtils.ts | 2 +- src/trading/getQuote.test.ts | 169 ++++++++++++++++++++ src/trading/getQuote.ts | 5 +- 3 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 src/trading/getQuote.test.ts diff --git a/src/order-book/quoteAmountsAndCostsUtils.ts b/src/order-book/quoteAmountsAndCostsUtils.ts index d934b68e..d1acab87 100644 --- a/src/order-book/quoteAmountsAndCostsUtils.ts +++ b/src/order-book/quoteAmountsAndCostsUtils.ts @@ -16,7 +16,7 @@ export function getQuoteAmountsAndCosts(params: Params): QuoteAmountsAndCosts { const partnerFeeBps = params.partnerFeeBps ?? 0 const isSell = orderParams.kind === OrderKind.SELL /** - * Wrap raw values into CurrencyAmount objects + * Wrap raw values into bigNumbers * We also make amounts names more specific with "beforeNetworkCosts" and "afterNetworkCosts" suffixes */ const networkCostAmount = getBigNumber(orderParams.feeAmount, sellDecimals) diff --git a/src/trading/getQuote.test.ts b/src/trading/getQuote.test.ts new file mode 100644 index 00000000..33cb09b6 --- /dev/null +++ b/src/trading/getQuote.test.ts @@ -0,0 +1,169 @@ +jest.mock('cross-fetch', () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fetchMock = require('jest-fetch-mock') + // Require the original module to not be mocked... + const originalFetch = jest.requireActual('cross-fetch') + return { + __esModule: true, + ...originalFetch, + default: fetchMock, + } +}) + +import { getQuote } from './getQuote' +import { SwapParameters } from './types' +import { ETH_ADDRESS, SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' +import { OrderBookApi, OrderKind, OrderQuoteResponse } from '../order-book' + +const quoteResponseMock = { + quote: { + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + receiver: '0xfb3c7eb936caa12b5a884d612393969a557d4307', + sellAmount: '98115217044683860', + buyAmount: '984440000000', + validTo: 1731059375, + appData: + '{"appCode":"CoW Swap","environment":"production","metadata":{"orderClass":{"orderClass":"market"},"quote":{"slippageBips":50,"smartSlippage":false}},"version":"1.3.0"}', + appDataHash: '0x05fb36aed7ba01f92544e72888fb354cdeab68b6bbb0b9ea5e64edc364093b42', + feeAmount: '1884782955316140', + kind: 'sell', + partiallyFillable: false, + sellTokenBalance: 'erc20', + buyTokenBalance: 'erc20', + signingScheme: 'eip712', + }, + from: '0xfb3c7eb936caa12b5a884d612393969a557d4307', + expiration: '2024-11-08T09:21:35.442772888Z', + id: 486289, + verified: true, +} as OrderQuoteResponse + +const defaultOrderParams: SwapParameters = { + chainId: SupportedChainId.GNOSIS_CHAIN, + signer: '1bb337bafb276f779c3035874b8914e4b851bb989dbb34e776397076576f3804', + appCode: '0x007', + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '100000000000000000', + kind: OrderKind.SELL, + slippageBps: 50, +} + +const getQuoteMock = jest.fn() +const orderBookApiMock = { + getQuote: getQuoteMock, +} as unknown as OrderBookApi + +describe('getQuote', () => { + beforeEach(() => { + getQuoteMock.mockReset() + getQuoteMock.mockResolvedValue(quoteResponseMock) + }) + + describe('App data', () => { + it('Should add slippageBps and appCode from parameters', async () => { + const result = await getQuote({ ...defaultOrderParams, slippageBps: 76 }, {}, orderBookApiMock) + const appData = JSON.parse(result.appDataInfo.fullAppData) + + expect(appData.metadata.quote.slippageBips).toBe(76) + expect(appData.appCode).toBe(defaultOrderParams.appCode) + }) + + it('Should add advanced appData parameters', async () => { + const result = await getQuote( + defaultOrderParams, + { + appData: { + environment: 'barn', + }, + }, + orderBookApiMock + ) + + const appData = JSON.parse(result.appDataInfo.fullAppData) + + expect(appData.environment).toBe('barn') + }) + }) + + describe('Quote request', () => { + it('When sell ETH, then should override sell token with wrapped one', async () => { + await getQuote({ ...defaultOrderParams, sellToken: ETH_ADDRESS }, {}, orderBookApiMock) + + const call = getQuoteMock.mock.calls[0][0] + + expect(call.sellToken).toBe(WRAPPED_NATIVE_CURRENCIES[defaultOrderParams.chainId]) + }) + it('Should add appData to the request', async () => { + await getQuote(defaultOrderParams, {}, orderBookApiMock) + + const call = getQuoteMock.mock.calls[0][0] + const appData = JSON.parse(call.appData) + + expect(appData.appCode).toBe(defaultOrderParams.appCode) + expect(appData.metadata.quote.slippageBips).toBe(defaultOrderParams.slippageBps) + }) + it('priceQuality must always be OPTIMAL', async () => { + await getQuote(defaultOrderParams, {}, orderBookApiMock) + + const call = getQuoteMock.mock.calls[0][0] + + expect(call.priceQuality).toBe('optimal') + }) + it('When is sell order, then should set sellAmountBeforeFee', async () => { + await getQuote({ ...defaultOrderParams, kind: OrderKind.SELL }, {}, orderBookApiMock) + + const call = getQuoteMock.mock.calls[0][0] + + expect(call.sellAmountBeforeFee).toBe(defaultOrderParams.amount) + }) + it('When is buy order, then should set buyAmountAfterFee', async () => { + await getQuote({ ...defaultOrderParams, kind: OrderKind.BUY }, {}, orderBookApiMock) + + const call = getQuoteMock.mock.calls[0][0] + + expect(call.buyAmountAfterFee).toBe(defaultOrderParams.amount) + }) + it('Should add advanced quote parameters', async () => { + await getQuote(defaultOrderParams, { quoteRequest: { onchainOrder: { foo: 'bar' } } }, orderBookApiMock) + + const call = getQuoteMock.mock.calls[0][0] + + expect(call.onchainOrder).toEqual({ foo: 'bar' }) + }) + }) + + describe('Amounts and costs', () => { + it('Should take slippage value into account', async () => { + const result = await getQuote({ ...defaultOrderParams, slippageBps: 20 }, {}, orderBookApiMock) + const buyAmount = quoteResponseMock.quote.buyAmount + + expect(+result.amountsAndCosts.afterSlippage.buyAmount.toString()).toBe( + +buyAmount - (+buyAmount * 20) / (100 * 100) + ) + }) + it('Should calculate network costs based on quote API response', async () => { + const result = await getQuote(defaultOrderParams, {}, orderBookApiMock) + + expect(result.amountsAndCosts.costs.networkFee.amountInSellCurrency.toString()).toBe( + quoteResponseMock.quote.feeAmount + ) + }) + }) + + describe('Order to sign', () => { + it('feeAmount should always be zero', async () => { + const result = await getQuote(defaultOrderParams, {}, orderBookApiMock) + + expect(result.orderToSign.feeAmount).toBe('0') + }) + it('Should add appDataKeccak256 to the order', async () => { + const result = await getQuote(defaultOrderParams, {}, orderBookApiMock) + + expect(result.orderToSign.appData.length).toBe(2 + 64) + }) + }) +}) diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index 8c1e1a2e..91633689 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -31,7 +31,8 @@ export interface QuoteResults { export async function getQuote( swapParameters: SwapParameters, - advancedSettings?: SwapAdvancedSettings + advancedSettings?: SwapAdvancedSettings, + _orderBookApi?: OrderBookApi ): Promise { const { appCode, @@ -51,7 +52,7 @@ export async function getQuote( log(`Swap ${amount} ${sellToken} for ${buyToken} on chain ${chainId}`) const signer = getSigner(swapParameters.signer) - const orderBookApi = new OrderBookApi({ chainId, env }) + const orderBookApi = _orderBookApi || new OrderBookApi({ chainId, env }) const from = await signer.getAddress() const receiver = swapParameters.receiver || from From 56692ab84b51e634ed255efc5d82755f890ef3a4 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 8 Nov 2024 15:42:57 +0500 Subject: [PATCH 19/67] test: test postCoWProtocolTrade --- src/trading/postCoWProtocolTrade.test.ts | 119 +++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/trading/postCoWProtocolTrade.test.ts diff --git a/src/trading/postCoWProtocolTrade.test.ts b/src/trading/postCoWProtocolTrade.test.ts new file mode 100644 index 00000000..5a876848 --- /dev/null +++ b/src/trading/postCoWProtocolTrade.test.ts @@ -0,0 +1,119 @@ +import { postCoWProtocolTrade } from './postCoWProtocolTrade' + +jest.mock('cross-fetch', () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fetchMock = require('jest-fetch-mock') + // Require the original module to not be mocked... + const originalFetch = jest.requireActual('cross-fetch') + return { + __esModule: true, + ...originalFetch, + default: fetchMock, + } +}) + +jest.mock('../order-signing', () => { + return { + OrderSigningUtils: { + signOrder: jest.fn(), + }, + } +}) + +jest.mock('./postOnChainTrade', () => { + return { + postOnChainTrade: jest.fn(), + } +}) + +import { postOnChainTrade } from './postOnChainTrade' + +import { AppDataInfo, LimitOrderParameters } from './types' +import { ETH_ADDRESS, SupportedChainId } from '../common' +import { OrderBookApi, OrderKind } from '../order-book' +import { OrderSigningUtils as OrderSigningUtilsMock } from '../order-signing' +import { VoidSigner } from '@ethersproject/abstract-signer' + +const defaultOrderParams: LimitOrderParameters = { + chainId: SupportedChainId.GNOSIS_CHAIN, + signer: '0x006', + appCode: '0x007', + sellToken: '0xaaa', + sellTokenDecimals: 18, + buyToken: '0xbbb', + buyTokenDecimals: 18, + sellAmount: '1000000000000000000', + buyAmount: '2000000000000000000', + kind: OrderKind.SELL, + quoteId: 31, + slippageBps: 50, +} + +const currentTimestamp = 1487076708000 + +const signatureMock = { signature: '0x000a1', signingScheme: 'eip712' } + +const signer = new VoidSigner('0x21c3de23d98caddc406e3d31b25e807addf33333') + +const sendOrderMock = jest.fn() +const orderBookApiMock = { + sendOrder: sendOrderMock, +} as unknown as OrderBookApi +const appDataMock = {} as unknown as AppDataInfo + +describe('postCoWProtocolTrade', () => { + let signOrderMock: jest.SpyInstance + let postOnChainTradeMock: jest.SpyInstance + + beforeAll(() => { + signOrderMock = OrderSigningUtilsMock.signOrder as unknown as jest.SpyInstance + postOnChainTradeMock = postOnChainTrade as unknown as jest.SpyInstance + }) + + beforeEach(() => { + Date.now = jest.fn(() => currentTimestamp) + signOrderMock.mockResolvedValue(signatureMock) + }) + + afterEach(() => { + signOrderMock.mockReset() + postOnChainTradeMock.mockReset() + sendOrderMock.mockReset() + }) + + it('When sell token is native, then should post on-chain order', async () => { + postOnChainTradeMock.mockResolvedValue({ orderId: '0x01' }) + + const order = { ...defaultOrderParams, sellToken: ETH_ADDRESS } + await postCoWProtocolTrade(orderBookApiMock, signer, appDataMock, order) + + expect(postOnChainTradeMock).toHaveBeenCalledTimes(1) + expect(postOnChainTradeMock).toHaveBeenCalledWith(orderBookApiMock, signer, appDataMock, order, '0') + }) + + it('API request should contain all specified parameters', async () => { + sendOrderMock.mockResolvedValue('0x02') + + const order = { ...defaultOrderParams } + await postCoWProtocolTrade(orderBookApiMock, signer, appDataMock, order) + + const callBody = sendOrderMock.mock.calls[0][0] + + expect(sendOrderMock).toHaveBeenCalledTimes(1) + expect(callBody).toEqual({ + sellToken: '0xaaa', + sellAmount: '1000000000000000000', + buyToken: '0xbbb', + buyAmount: '1990000000000000000', // Slippage is taken into account + feeAmount: '0', + from: '0x21c3de23d98caddc406e3d31b25e807addf33333', + kind: 'sell', + partiallyFillable: false, + quoteId: 31, + receiver: '0x21c3de23d98caddc406e3d31b25e807addf33333', + signature: '0x000a1', + signingScheme: 'eip712', + validTo: 1487077308, + }) + }) +}) From 9d828bf7d3992089b11ef93a9309d334bf9228d4 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 8 Nov 2024 16:04:58 +0500 Subject: [PATCH 20/67] test: test postLimitOrder --- src/trading/postLimitOrder.test.ts | 94 ++++++++++++++++++++++++++++++ src/trading/postLimitOrder.ts | 27 +++------ src/trading/postSwapOrder.ts | 2 +- 3 files changed, 103 insertions(+), 20 deletions(-) create mode 100644 src/trading/postLimitOrder.test.ts diff --git a/src/trading/postLimitOrder.test.ts b/src/trading/postLimitOrder.test.ts new file mode 100644 index 00000000..6883593b --- /dev/null +++ b/src/trading/postLimitOrder.test.ts @@ -0,0 +1,94 @@ +jest.mock('cross-fetch', () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fetchMock = require('jest-fetch-mock') + // Require the original module to not be mocked... + const originalFetch = jest.requireActual('cross-fetch') + return { + __esModule: true, + ...originalFetch, + default: fetchMock, + } +}) + +jest.mock('./postCoWProtocolTrade', () => { + return { + postCoWProtocolTrade: jest.fn(), + } +}) + +jest.mock('./appDataUtils', () => { + return { + buildAppData: jest.fn(), + } +}) + +import { postCoWProtocolTrade } from './postCoWProtocolTrade' +import { buildAppData } from './appDataUtils' + +import { AppDataInfo, LimitOrderParameters } from './types' +import { SupportedChainId } from '../common' +import { OrderBookApi, OrderKind } from '../order-book' +import { postLimitOrder } from './postLimitOrder' + +const defaultOrderParams: LimitOrderParameters = { + chainId: SupportedChainId.GNOSIS_CHAIN, + signer: '1bb337bafb276f779c3035874b8914e4b851bb989dbb34e776397076576f3804', + appCode: '0x007', + sellToken: '0xaaa', + sellTokenDecimals: 18, + buyToken: '0xbbb', + buyTokenDecimals: 18, + sellAmount: '1000000000000000000', + buyAmount: '2000000000000000000', + kind: OrderKind.SELL, + quoteId: 31, + slippageBps: 50, +} + +const currentTimestamp = 1487076708000 + +const orderBookApiMock = {} as unknown as OrderBookApi +const appDataMock = {} as unknown as AppDataInfo + +describe('postLimitOrder', () => { + let buildAppDataMock: jest.SpyInstance + let postCoWProtocolTradeMock: jest.SpyInstance + + beforeAll(() => { + buildAppDataMock = buildAppData as unknown as jest.SpyInstance + postCoWProtocolTradeMock = postCoWProtocolTrade as unknown as jest.SpyInstance + }) + + beforeEach(() => { + Date.now = jest.fn(() => currentTimestamp) + + buildAppDataMock.mockResolvedValue(appDataMock) + }) + + afterEach(() => { + buildAppDataMock.mockReset() + postCoWProtocolTradeMock.mockReset() + }) + + it('Should add advanced appData parameters', async () => { + const advancedData = { appData: { environment: 'sandbox' } } + + await postLimitOrder(defaultOrderParams, advancedData, orderBookApiMock) + + const call = buildAppDataMock.mock.calls[0][1] + + expect(call).toEqual(advancedData.appData) + }) + + it('Should call order posting with all specified parameters', async () => { + await postLimitOrder(defaultOrderParams, {}, orderBookApiMock) + + expect(postCoWProtocolTradeMock).toHaveBeenCalledTimes(1) + expect(postCoWProtocolTradeMock).toHaveBeenCalledWith( + orderBookApiMock, + expect.anything(), + appDataMock, + defaultOrderParams + ) + }) +}) diff --git a/src/trading/postLimitOrder.ts b/src/trading/postLimitOrder.ts index f3711d60..51f6b605 100644 --- a/src/trading/postLimitOrder.ts +++ b/src/trading/postLimitOrder.ts @@ -5,23 +5,17 @@ import { buildAppData } from './appDataUtils' import { postCoWProtocolTrade } from './postCoWProtocolTrade' import { getSigner } from './utils' -export async function postLimitOrder(params: LimitOrderParameters, advancedSettings?: LimitOrderAdvancedSettings) { - const { - appCode, - chainId, - sellToken, - buyToken, - sellAmount, - buyAmount, - quoteId, - slippageBps = 0, - env = 'prod', - } = params +export async function postLimitOrder( + params: LimitOrderParameters, + advancedSettings?: LimitOrderAdvancedSettings, + _orderBookApi?: OrderBookApi +): Promise { + const { appCode, chainId, sellToken, buyToken, sellAmount, buyAmount, slippageBps = 0, env = 'prod' } = params log(`Limit order ${sellAmount} ${sellToken} for ${buyAmount} ${buyToken} on chain ${chainId}`) const signer = getSigner(params.signer) - const orderBookApi = new OrderBookApi({ chainId, env }) + const orderBookApi = _orderBookApi || new OrderBookApi({ chainId, env }) log('Building app data...') @@ -34,10 +28,5 @@ export async function postLimitOrder(params: LimitOrderParameters, advancedSetti advancedSettings?.appData ) - return postCoWProtocolTrade(orderBookApi, signer, appDataInfo, { - ...params, - quoteId, - sellAmount, - buyAmount, - }) + return postCoWProtocolTrade(orderBookApi, signer, appDataInfo, params) } diff --git a/src/trading/postSwapOrder.ts b/src/trading/postSwapOrder.ts index f85562c3..b5ffd6e9 100644 --- a/src/trading/postSwapOrder.ts +++ b/src/trading/postSwapOrder.ts @@ -14,7 +14,7 @@ export async function postSwapOrderFromQuote({ appDataInfo, quoteResponse, swapParameters, -}: QuoteResults) { +}: QuoteResults): Promise { return postCoWProtocolTrade( orderBookApi, signer, From f106189cfb7fa82d329f23f5f02230f0e8a88a25 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 8 Nov 2024 17:18:00 +0500 Subject: [PATCH 21/67] test: test postOnChainTrade --- src/trading/getOrderToSign.ts | 4 +- src/trading/postOnChainTrade.test.ts | 135 +++++++++++++++++++++++++++ src/trading/postOnChainTrade.ts | 2 +- 3 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 src/trading/postOnChainTrade.test.ts diff --git a/src/trading/getOrderToSign.ts b/src/trading/getOrderToSign.ts index 646e5633..1c421f0e 100644 --- a/src/trading/getOrderToSign.ts +++ b/src/trading/getOrderToSign.ts @@ -1,4 +1,4 @@ -import { getQuoteAmountsAndCosts, type OrderParameters } from '../order-book' +import { BuyTokenDestination, getQuoteAmountsAndCosts, type OrderParameters, SellTokenSource } from '../order-book' import { UnsignedOrder } from '../order-signing' import { LimitOrderParameters } from './types' import { DEFAULT_QUOTE_VALIDITY } from './consts' @@ -62,5 +62,7 @@ export function getOrderToSign( appData: appDataKeccak256, receiver, feeAmount: '0', + sellTokenBalance: SellTokenSource.ERC20, + buyTokenBalance: BuyTokenDestination.ERC20, } } diff --git a/src/trading/postOnChainTrade.test.ts b/src/trading/postOnChainTrade.test.ts new file mode 100644 index 00000000..54ff52e4 --- /dev/null +++ b/src/trading/postOnChainTrade.test.ts @@ -0,0 +1,135 @@ +import { EthFlow__factory } from '../common/generated' + +jest.mock('cross-fetch', () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fetchMock = require('jest-fetch-mock') + // Require the original module to not be mocked... + const originalFetch = jest.requireActual('cross-fetch') + return { + __esModule: true, + ...originalFetch, + default: fetchMock, + } +}) + +jest.mock('../common/generated', () => { + const original = jest.requireActual('../common/generated') + + return { + ...original, + EthFlow__factory: { + connect: jest.fn(), + }, + } +}) + +import { VoidSigner } from '@ethersproject/abstract-signer' +import { AppDataInfo, LimitOrderParameters } from './types' +import { SupportedChainId } from '../common' +import { OrderBookApi, OrderKind } from '../order-book' +import { postOnChainTrade } from './postOnChainTrade' + +const defaultOrderParams: LimitOrderParameters = { + chainId: SupportedChainId.GNOSIS_CHAIN, + signer: '1bb337bafb276f779c3035874b8914e4b851bb989dbb34e776397076576f3804', + appCode: '0x007', + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + sellAmount: '1000000000000000000', + buyAmount: '2000000000000000000', + kind: OrderKind.SELL, + quoteId: 31, + slippageBps: 50, + validTo: 520, +} + +const account = '0x21c3de23d98caddc406e3d31b25e807addf33333' +const signer = new VoidSigner(account) + +const currentTimestamp = 1487076708000 + +const uploadAppDataMock = jest.fn() +const orderBookApiMock = { uploadAppData: uploadAppDataMock } as unknown as OrderBookApi +const appDataMock = { + appDataKeccak256: '0xaf1908d8e30f63bf4a6dbd41d2191eb092ac0af626b37c720596426130717658', + fullAppData: + '{\\"appCode\\":\\"CoW Swap\\",\\"environment\\":\\"barn\\",\\"metadata\\":{\\"orderClass\\":{\\"orderClass\\":\\"market\\"},\\"quote\\":{\\"slippageBips\\":201,\\"smartSlippage\\":true}},\\"version\\":\\"1.3.0\\"}', +} as unknown as AppDataInfo + +let ethFlowContractFactoryMock: jest.SpyInstance +const ethFlowContractMock = { + estimateGas: { + createOrder: jest.fn(), + }, + createOrder: jest.fn(), +} + +describe('postOnChainTrade', () => { + beforeAll(() => { + ethFlowContractFactoryMock = EthFlow__factory.connect as unknown as jest.SpyInstance + }) + + beforeEach(() => { + ethFlowContractFactoryMock.mockReturnValue(ethFlowContractMock) + uploadAppDataMock.mockResolvedValue(undefined) + ethFlowContractMock.estimateGas.createOrder.mockResolvedValue({ toHexString: () => '0x1' }) + ethFlowContractMock.createOrder.mockResolvedValue({ hash: '0x000cc' }) + + Date.now = jest.fn(() => currentTimestamp) + }) + + afterEach(() => { + uploadAppDataMock.mockReset() + ethFlowContractFactoryMock.mockReset() + }) + + it('Should call checkEthFlowOrderExists if it is set', async () => { + const checkEthFlowOrderExists = jest.fn().mockResolvedValue(false) + + await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams, '0', checkEthFlowOrderExists) + + expect(checkEthFlowOrderExists).toHaveBeenCalledTimes(1) + }) + + it('Should upload appData', async () => { + await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) + + expect(uploadAppDataMock).toHaveBeenCalledWith(appDataMock.appDataKeccak256, appDataMock.fullAppData) + }) + + it('When transaction gas estimation is failed, then should use fallback value + 20%', async () => { + ethFlowContractMock.estimateGas.createOrder.mockRejectedValue(new Error('Estimation failed')) + + await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) + + const call = ethFlowContractMock.createOrder.mock.calls[0][1] + + expect(call.gasLimit).toBe(BigInt(180000)) // 150000 by default + 20% + }) + + it('Should create an on-chain transaction with all specified parameters', async () => { + await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) + + expect(ethFlowContractMock.createOrder).toHaveBeenCalledTimes(1) + expect(ethFlowContractMock.createOrder).toHaveBeenCalledWith( + { + appData: appDataMock.appDataKeccak256, + sellToken: defaultOrderParams.sellToken, + sellAmount: defaultOrderParams.sellAmount, + sellTokenBalance: 'erc20', + buyAmount: '1990000000000000000', // defaultOrderParams.buyAmount - slippage + buyToken: defaultOrderParams.buyToken, + buyTokenBalance: 'erc20', + feeAmount: '0', + partiallyFillable: false, + kind: defaultOrderParams.kind, + quoteId: defaultOrderParams.quoteId, + receiver: account, + validTo: defaultOrderParams.validTo!.toString(), + }, + { value: defaultOrderParams.sellAmount, gasLimit: BigInt(1) } + ) + }) +}) diff --git a/src/trading/postOnChainTrade.ts b/src/trading/postOnChainTrade.ts index 60f0c839..8e687c67 100644 --- a/src/trading/postOnChainTrade.ts +++ b/src/trading/postOnChainTrade.ts @@ -11,7 +11,7 @@ import { OrderBookApi } from '../order-book' export async function postOnChainTrade( orderBookApi: OrderBookApi, signer: Signer, - appData: AppDataInfo, + appData: Pick, params: LimitOrderParameters, networkCostsAmount = '0', checkEthFlowOrderExists?: EthFlowOrderExistsCallback From 99a1cadb478627b32fa8b25e4b70f014b9ca7b8c Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 8 Nov 2024 17:29:07 +0500 Subject: [PATCH 22/67] docs: docs for postOnChainTrade --- src/trading/README.md | 39 +++++++++++++++++++++++++++++++++++++++ src/trading/index.ts | 1 + src/trading/tradingSdk.ts | 13 +++++++++++++ 3 files changed, 53 insertions(+) diff --git a/src/trading/README.md b/src/trading/README.md index 5fbde60d..a7b59437 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -54,6 +54,8 @@ The parameters required are: - `buyTokenDecimals` - the buy token decimals - `amount` - the amount to sell/buy in atoms +> When sell token is a blockchain native token (ETH for Ethereum), then order will be created as an on-chain transaction. See [postOnChainTrade](#postOnChainTrade) + #### Example ```typescript @@ -180,6 +182,43 @@ const orderId = await sdk.postLimitOrder(limitOrderParameters) console.log('Order created, id: ', orderId) ``` +### postOnChainTrade + +CoW Protocol supports on-chain trades for selling blockchain native tokens (ETH for Ethereum). +In this case, the order is created as an on-chain transaction. +You don't have to think about the case when you use `postSwapOrder` function, it will be handled automatically. +But if you need more flexible way to create an on-chain order, you can use the `postOnChainTrade` function. + +> We consider the order as an on-chain trade if the sell token has '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' address. + +```typescript +import { + SupportedChainId, + OrderKind, + TradeParameters, + TradingSdk +} from '@cowprotocol/sdk' + +const sdk = new TradingSdk({ + chainId: SupportedChainId.SEPOLIA, + signer: '', + appCode: '', +}) + +const parameters: TradeParameters = { + kind: OrderKind.BUY, + sellToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '120000000000000000' +} + +const orderId = await sdk.postOnChainTrade(parameters) + +console.log('Order created, id: ', orderId) +``` + ### Advanced swap order creation By default, the SDK requires only the basic parameters to create an order. diff --git a/src/trading/index.ts b/src/trading/index.ts index cb6eba45..e2ebd35a 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -6,3 +6,4 @@ export { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' export { postLimitOrder } from './postLimitOrder' export { postCoWProtocolTrade } from './postCoWProtocolTrade' export { getOrderToSign } from './getOrderToSign' +export { postOnChainTrade } from './postOnChainTrade' diff --git a/src/trading/tradingSdk.ts b/src/trading/tradingSdk.ts index c887b5ea..83ce60b3 100644 --- a/src/trading/tradingSdk.ts +++ b/src/trading/tradingSdk.ts @@ -9,6 +9,8 @@ import { import { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' import { postLimitOrder } from './postLimitOrder' import { getQuote } from './getQuote' +import { postOnChainTrade } from './postOnChainTrade' +import { swapParamsToLimitOrderParams } from './utils' export class TradingSdk { constructor(public readonly traderParams: TraderParameters) {} @@ -21,6 +23,17 @@ export class TradingSdk { return postLimitOrder(this.mergeParams(params), advancedSettings) } + async postOnChainTrade(params: TradeParameters, advancedSettings?: SwapAdvancedSettings) { + const quoteResults = await getQuote(this.mergeParams(params), advancedSettings) + + return postOnChainTrade( + quoteResults.orderBookApi, + quoteResults.signer, + quoteResults.appDataInfo, + swapParamsToLimitOrderParams(quoteResults.swapParameters, quoteResults.quoteResponse) + ) + } + async getQuote(params: TradeParameters, advancedSettings?: SwapAdvancedSettings): Promise { const quoteResults = await getQuote(this.mergeParams(params), advancedSettings) From 03d212ec36574e5082b2c51d4a9196be722099ad Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 8 Nov 2024 17:32:23 +0500 Subject: [PATCH 23/67] chore: up docs --- src/trading/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/trading/README.md b/src/trading/README.md index a7b59437..70c04aad 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -16,6 +16,7 @@ It will put all necessary parameters to your order, calculates proper amounts, a - quote API (priceQuality, signingScheme, etc.) - order kind (sell/buy) - order class (swap/limit/and others) + - on-chain trades ## TradingSdk @@ -28,7 +29,7 @@ The SDK provides three main functions: The SDK requires the following parameters: - `chainId` - one of supported chain ids (see [`SupportedChainId`](../common/chains.ts)) - - `signer` - private key or ethers signer. The signer is used to sign the order. If you use a private key, the SDK will create an ethers signer from it. If you use an ethers signer, the SDK will use it directly. + - `signer` - private key or ethers signer or `Eip1193` provider. The signer is used to sign the order. If you use a private key, the SDK will create an ethers signer from it. If you use an ethers signer, the SDK will use it directly. - `appCode` - a unique identifier for your application. It is used to identify orders created by your application. #### Example From 867b05eec8dab9b90e1fca5243a5dcf3ab197773 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 8 Nov 2024 17:38:45 +0500 Subject: [PATCH 24/67] fix: update eth-flow addresses --- src/common/consts.ts | 15 ++++++++------- src/trading/calculateUniqueOrderId.ts | 14 +++++++++++--- src/trading/postOnChainTrade.ts | 13 ++++++++----- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/common/consts.ts b/src/common/consts.ts index e3790e14..1faaee91 100644 --- a/src/common/consts.ts +++ b/src/common/consts.ts @@ -72,14 +72,15 @@ export const ETH_FLOW_ADDRESSES: Record = { [SupportedChainId.GNOSIS_CHAIN]: '0x40A50cf069e992AA4536211B23F286eF88752187', [SupportedChainId.ARBITRUM_ONE]: '0x552fcecc218158fff20e505c8f3ad24f8e1dd33c', [SupportedChainId.SEPOLIA]: '0x0b7795E18767259CC253a2dF471db34c72B49516', - [SupportedChainId.BASE]: 'TODO', // TODO + [SupportedChainId.BASE]: '0x40A50cf069e992AA4536211B23F286eF88752187', } -// const BARN_ETH_FLOW_ADDRESSES: Record = { -// [SupportedChainId.MAINNET]: '0xD02De8Da0B71E1B59489794F423FaBBa2AdC4d93', -// [SupportedChainId.GNOSIS_CHAIN]: '0xD02De8Da0B71E1B59489794F423FaBBa2AdC4d93', -// [SupportedChainId.ARBITRUM_ONE]: '0x6dfe75b5ddce1ade279d4fa6bd6aef3cbb6f49db', -// [SupportedChainId.SEPOLIA]: '0x2671994c7D224ac4799ac2cf6Ef9EF187d42C69f', -// } +export const BARN_ETH_FLOW_ADDRESSES: Record = { + [SupportedChainId.MAINNET]: '0xD02De8Da0B71E1B59489794F423FaBBa2AdC4d93', + [SupportedChainId.GNOSIS_CHAIN]: '0xD02De8Da0B71E1B59489794F423FaBBa2AdC4d93', + [SupportedChainId.ARBITRUM_ONE]: '0x6dfe75b5ddce1ade279d4fa6bd6aef3cbb6f49db', + [SupportedChainId.SEPOLIA]: '0x2671994c7D224ac4799ac2cf6Ef9EF187d42C69f', + [SupportedChainId.BASE]: '0xD02De8Da0B71E1B59489794F423FaBBa2AdC4d93', +} export const MAX_VALID_TO_EPOCH = 4294967295 // Max uint32 (Feb 07 2106 07:28:15 GMT+0100) diff --git a/src/trading/calculateUniqueOrderId.ts b/src/trading/calculateUniqueOrderId.ts index 5d7e4a8e..418d9b72 100644 --- a/src/trading/calculateUniqueOrderId.ts +++ b/src/trading/calculateUniqueOrderId.ts @@ -1,5 +1,12 @@ import { OrderSigningUtils, UnsignedOrder } from '../order-signing' -import { ETH_FLOW_ADDRESSES, MAX_VALID_TO_EPOCH, SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' +import { + BARN_ETH_FLOW_ADDRESSES, + CowEnv, + ETH_FLOW_ADDRESSES, + MAX_VALID_TO_EPOCH, + SupportedChainId, + WRAPPED_NATIVE_CURRENCIES, +} from '../common' import type { Order, OrderBalance } from '@cowprotocol/contracts' export interface EthFlowOrderExistsCallback { @@ -9,7 +16,8 @@ export interface EthFlowOrderExistsCallback { export async function calculateUniqueOrderId( chainId: SupportedChainId, order: UnsignedOrder, - checkEthFlowOrderExists?: EthFlowOrderExistsCallback + checkEthFlowOrderExists?: EthFlowOrderExistsCallback, + env?: CowEnv ): Promise { const { orderDigest, orderId } = await OrderSigningUtils.generateOrderId( chainId, @@ -21,7 +29,7 @@ export async function calculateUniqueOrderId( sellToken: WRAPPED_NATIVE_CURRENCIES[chainId], } as Order, { - owner: ETH_FLOW_ADDRESSES[chainId], + owner: (env === 'staging' ? BARN_ETH_FLOW_ADDRESSES : ETH_FLOW_ADDRESSES)[chainId], } ) diff --git a/src/trading/postOnChainTrade.ts b/src/trading/postOnChainTrade.ts index 8e687c67..36da2241 100644 --- a/src/trading/postOnChainTrade.ts +++ b/src/trading/postOnChainTrade.ts @@ -3,7 +3,7 @@ import { AppDataInfo, LimitOrderParameters } from './types' import { calculateUniqueOrderId, EthFlowOrderExistsCallback } from './calculateUniqueOrderId' import { getOrderToSign } from './getOrderToSign' import { type EthFlow, EthFlow__factory } from '../common/generated' -import { ETH_FLOW_ADDRESSES, SupportedChainId } from '../common' +import { BARN_ETH_FLOW_ADDRESSES, CowEnv, ETH_FLOW_ADDRESSES, SupportedChainId } from '../common' import { GAS_LIMIT_DEFAULT, log } from './consts' import type { EthFlowOrder } from '../common/generated/EthFlow' import { OrderBookApi } from '../order-book' @@ -21,9 +21,9 @@ export async function postOnChainTrade( const from = await signer.getAddress() - const contract = getEthFlowContract(chainId, signer) + const contract = getEthFlowContract(chainId, signer, params.env) const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appDataKeccak256) - const orderId = await calculateUniqueOrderId(chainId, orderToSign, checkEthFlowOrderExists) + const orderId = await calculateUniqueOrderId(chainId, orderToSign, checkEthFlowOrderExists, params.env) const ethOrderParams: EthFlowOrder.DataStruct = { ...orderToSign, @@ -57,12 +57,15 @@ export async function postOnChainTrade( const ethFlowContractCache: Partial> = {} -function getEthFlowContract(chainId: SupportedChainId, signer: Signer): EthFlow { +function getEthFlowContract(chainId: SupportedChainId, signer: Signer, env?: CowEnv): EthFlow { const cache = ethFlowContractCache[chainId] if (cache) return cache - const contract = EthFlow__factory.connect(ETH_FLOW_ADDRESSES[chainId], signer) + const contract = EthFlow__factory.connect( + (env === 'staging' ? BARN_ETH_FLOW_ADDRESSES : ETH_FLOW_ADDRESSES)[chainId], + signer + ) ethFlowContractCache[chainId] = contract From 62ee519dce9490a2fffe4907aed810417770a434 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 8 Nov 2024 17:46:15 +0500 Subject: [PATCH 25/67] chore: fix tests --- src/trading/postCoWProtocolTrade.test.ts | 10 +++++++++- src/trading/postOnChainTrade.test.ts | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/trading/postCoWProtocolTrade.test.ts b/src/trading/postCoWProtocolTrade.test.ts index 5a876848..59a1f00e 100644 --- a/src/trading/postCoWProtocolTrade.test.ts +++ b/src/trading/postCoWProtocolTrade.test.ts @@ -59,7 +59,11 @@ const sendOrderMock = jest.fn() const orderBookApiMock = { sendOrder: sendOrderMock, } as unknown as OrderBookApi -const appDataMock = {} as unknown as AppDataInfo +const appDataMock = { + appDataKeccak256: '0xaf1908d8e30f63bf4a6dbd41d2191eb092ac0af626b37c720596426130717658', + fullAppData: + '{\\"appCode\\":\\"CoW Swap\\",\\"environment\\":\\"barn\\",\\"metadata\\":{\\"orderClass\\":{\\"orderClass\\":\\"market\\"},\\"quote\\":{\\"slippageBips\\":201,\\"smartSlippage\\":true}},\\"version\\":\\"1.3.0\\"}', +} as unknown as AppDataInfo describe('postCoWProtocolTrade', () => { let signOrderMock: jest.SpyInstance @@ -101,10 +105,14 @@ describe('postCoWProtocolTrade', () => { expect(sendOrderMock).toHaveBeenCalledTimes(1) expect(callBody).toEqual({ + appData: appDataMock.fullAppData, + appDataHash: appDataMock.appDataKeccak256, sellToken: '0xaaa', sellAmount: '1000000000000000000', + sellTokenBalance: 'erc20', buyToken: '0xbbb', buyAmount: '1990000000000000000', // Slippage is taken into account + buyTokenBalance: 'erc20', feeAmount: '0', from: '0x21c3de23d98caddc406e3d31b25e807addf33333', kind: 'sell', diff --git a/src/trading/postOnChainTrade.test.ts b/src/trading/postOnChainTrade.test.ts index 54ff52e4..963e138c 100644 --- a/src/trading/postOnChainTrade.test.ts +++ b/src/trading/postOnChainTrade.test.ts @@ -83,6 +83,8 @@ describe('postOnChainTrade', () => { afterEach(() => { uploadAppDataMock.mockReset() ethFlowContractFactoryMock.mockReset() + ethFlowContractMock.estimateGas.createOrder.mockReset() + ethFlowContractMock.createOrder.mockReset() }) it('Should call checkEthFlowOrderExists if it is set', async () => { From 4f788edbee6f483a27617b9c0d9b084c5d999668 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 8 Nov 2024 17:53:50 +0500 Subject: [PATCH 26/67] chore: export helpers --- src/trading/index.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/trading/index.ts b/src/trading/index.ts index e2ebd35a..84835277 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -1,9 +1,19 @@ export * from './types' export * from './tradingSdk' +/** + * Main trading functions + */ export { getQuote } from './getQuote' export { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' export { postLimitOrder } from './postLimitOrder' export { postCoWProtocolTrade } from './postCoWProtocolTrade' export { getOrderToSign } from './getOrderToSign' export { postOnChainTrade } from './postOnChainTrade' + +/** + * Helpers + */ + +export * from './appDataUtils' +export * from './calculateUniqueOrderId' From 953f84860b5d6af1f0509661b1095d75cf0f841c Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 12 Nov 2024 11:52:58 +0700 Subject: [PATCH 27/67] chore: rc version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4c4c7561..d8541f73 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "5.7.1", + "version": "5.8.0-RC.0", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" From 2338f92d922f2c903e37e12ed3ecbd408046265a Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Mon, 18 Nov 2024 17:59:47 +0500 Subject: [PATCH 28/67] chore: fix readme --- src/trading/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/trading/README.md b/src/trading/README.md index 70c04aad..b3d4167a 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -34,7 +34,7 @@ The SDK requires the following parameters: #### Example ```typescript -import { SupportedChainId, TradingSdk } from '@cowprotocol/sdk' +import { SupportedChainId, TradingSdk } from '@cowprotocol/cow-sdk' const sdk = new TradingSdk({ chainId: SupportedChainId.SEPOLIA, @@ -65,7 +65,7 @@ import { OrderKind, TradeParameters, TradingSdk -} from '@cowprotocol/sdk' +} from '@cowprotocol/cow-sdk' const sdk = new TradingSdk({ chainId: SupportedChainId.SEPOLIA, @@ -113,7 +113,7 @@ import { OrderKind, TradeParameters, TradingSdk -} from '@cowprotocol/sdk' +} from '@cowprotocol/cow-sdk' const sdk = new TradingSdk({ chainId: SupportedChainId.SEPOLIA, @@ -160,7 +160,7 @@ import { OrderKind, LimitTradeParameters, TradingSdk -} from '@cowprotocol/sdk' +} from '@cowprotocol/cow-sdk' const sdk = new TradingSdk({ chainId: SupportedChainId.SEPOLIA, @@ -198,7 +198,7 @@ import { OrderKind, TradeParameters, TradingSdk -} from '@cowprotocol/sdk' +} from '@cowprotocol/cow-sdk' const sdk = new TradingSdk({ chainId: SupportedChainId.SEPOLIA, @@ -240,7 +240,7 @@ import { TradingSdk, SwapAdvancedSettings, PriceQuality -} from '@cowprotocol/sdk' +} from '@cowprotocol/cow-sdk' const sdk = new TradingSdk({ chainId: SupportedChainId.SEPOLIA, @@ -275,7 +275,7 @@ const advancedSettings: SwapAdvancedSettings = { } }, } -const orderId = await sdk.postSwapOrder(parameters) +const orderId = await sdk.postSwapOrder(parameters, advancedSettings) console.log('Order created, id: ', orderId) ``` From 6b8a7a2c129a65032ab8af6932043fc5a2e57b19 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 19 Nov 2024 13:37:24 +0500 Subject: [PATCH 29/67] feat: avoid using signer in getQuote --- src/trading/getOrderToSign.ts | 4 +- src/trading/getQuote.test.ts | 28 ++++++------ src/trading/getQuote.ts | 54 ++++++++++++++++++------ src/trading/index.ts | 2 +- src/trading/postCoWProtocolTrade.test.ts | 1 + src/trading/postCoWProtocolTrade.ts | 7 +-- src/trading/postOnChainTrade.test.ts | 1 + src/trading/postOnChainTrade.ts | 7 +-- src/trading/postSwapOrder.ts | 10 ++--- src/trading/tradingSdk.ts | 8 ++-- src/trading/types.ts | 7 ++- src/trading/utils.ts | 14 +++--- 12 files changed, 91 insertions(+), 52 deletions(-) diff --git a/src/trading/getOrderToSign.ts b/src/trading/getOrderToSign.ts index 1c421f0e..1b0992e1 100644 --- a/src/trading/getOrderToSign.ts +++ b/src/trading/getOrderToSign.ts @@ -1,6 +1,6 @@ import { BuyTokenDestination, getQuoteAmountsAndCosts, type OrderParameters, SellTokenSource } from '../order-book' import { UnsignedOrder } from '../order-signing' -import { LimitOrderParameters } from './types' +import { LimitTradeParameters } from './types' import { DEFAULT_QUOTE_VALIDITY } from './consts' interface OrderToSignParams { @@ -10,7 +10,7 @@ interface OrderToSignParams { export function getOrderToSign( { from, networkCostsAmount = '0' }: OrderToSignParams, - limitOrderParams: LimitOrderParameters, + limitOrderParams: LimitTradeParameters, appDataKeccak256: string ): UnsignedOrder { const { diff --git a/src/trading/getQuote.test.ts b/src/trading/getQuote.test.ts index 33cb09b6..c2596e7e 100644 --- a/src/trading/getQuote.test.ts +++ b/src/trading/getQuote.test.ts @@ -10,7 +10,7 @@ jest.mock('cross-fetch', () => { } }) -import { getQuote } from './getQuote' +import { getQuoteWithSigner } from './getQuote' import { SwapParameters } from './types' import { ETH_ADDRESS, SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' import { OrderBookApi, OrderKind, OrderQuoteResponse } from '../order-book' @@ -57,7 +57,7 @@ const orderBookApiMock = { getQuote: getQuoteMock, } as unknown as OrderBookApi -describe('getQuote', () => { +describe('getQuoteToSign', () => { beforeEach(() => { getQuoteMock.mockReset() getQuoteMock.mockResolvedValue(quoteResponseMock) @@ -65,7 +65,7 @@ describe('getQuote', () => { describe('App data', () => { it('Should add slippageBps and appCode from parameters', async () => { - const result = await getQuote({ ...defaultOrderParams, slippageBps: 76 }, {}, orderBookApiMock) + const result = await getQuoteWithSigner({ ...defaultOrderParams, slippageBps: 76 }, {}, orderBookApiMock) const appData = JSON.parse(result.appDataInfo.fullAppData) expect(appData.metadata.quote.slippageBips).toBe(76) @@ -73,7 +73,7 @@ describe('getQuote', () => { }) it('Should add advanced appData parameters', async () => { - const result = await getQuote( + const result = await getQuoteWithSigner( defaultOrderParams, { appData: { @@ -91,14 +91,14 @@ describe('getQuote', () => { describe('Quote request', () => { it('When sell ETH, then should override sell token with wrapped one', async () => { - await getQuote({ ...defaultOrderParams, sellToken: ETH_ADDRESS }, {}, orderBookApiMock) + await getQuoteWithSigner({ ...defaultOrderParams, sellToken: ETH_ADDRESS }, {}, orderBookApiMock) const call = getQuoteMock.mock.calls[0][0] expect(call.sellToken).toBe(WRAPPED_NATIVE_CURRENCIES[defaultOrderParams.chainId]) }) it('Should add appData to the request', async () => { - await getQuote(defaultOrderParams, {}, orderBookApiMock) + await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) const call = getQuoteMock.mock.calls[0][0] const appData = JSON.parse(call.appData) @@ -107,28 +107,28 @@ describe('getQuote', () => { expect(appData.metadata.quote.slippageBips).toBe(defaultOrderParams.slippageBps) }) it('priceQuality must always be OPTIMAL', async () => { - await getQuote(defaultOrderParams, {}, orderBookApiMock) + await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) const call = getQuoteMock.mock.calls[0][0] expect(call.priceQuality).toBe('optimal') }) it('When is sell order, then should set sellAmountBeforeFee', async () => { - await getQuote({ ...defaultOrderParams, kind: OrderKind.SELL }, {}, orderBookApiMock) + await getQuoteWithSigner({ ...defaultOrderParams, kind: OrderKind.SELL }, {}, orderBookApiMock) const call = getQuoteMock.mock.calls[0][0] expect(call.sellAmountBeforeFee).toBe(defaultOrderParams.amount) }) it('When is buy order, then should set buyAmountAfterFee', async () => { - await getQuote({ ...defaultOrderParams, kind: OrderKind.BUY }, {}, orderBookApiMock) + await getQuoteWithSigner({ ...defaultOrderParams, kind: OrderKind.BUY }, {}, orderBookApiMock) const call = getQuoteMock.mock.calls[0][0] expect(call.buyAmountAfterFee).toBe(defaultOrderParams.amount) }) it('Should add advanced quote parameters', async () => { - await getQuote(defaultOrderParams, { quoteRequest: { onchainOrder: { foo: 'bar' } } }, orderBookApiMock) + await getQuoteWithSigner(defaultOrderParams, { quoteRequest: { onchainOrder: { foo: 'bar' } } }, orderBookApiMock) const call = getQuoteMock.mock.calls[0][0] @@ -138,7 +138,7 @@ describe('getQuote', () => { describe('Amounts and costs', () => { it('Should take slippage value into account', async () => { - const result = await getQuote({ ...defaultOrderParams, slippageBps: 20 }, {}, orderBookApiMock) + const result = await getQuoteWithSigner({ ...defaultOrderParams, slippageBps: 20 }, {}, orderBookApiMock) const buyAmount = quoteResponseMock.quote.buyAmount expect(+result.amountsAndCosts.afterSlippage.buyAmount.toString()).toBe( @@ -146,7 +146,7 @@ describe('getQuote', () => { ) }) it('Should calculate network costs based on quote API response', async () => { - const result = await getQuote(defaultOrderParams, {}, orderBookApiMock) + const result = await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) expect(result.amountsAndCosts.costs.networkFee.amountInSellCurrency.toString()).toBe( quoteResponseMock.quote.feeAmount @@ -156,12 +156,12 @@ describe('getQuote', () => { describe('Order to sign', () => { it('feeAmount should always be zero', async () => { - const result = await getQuote(defaultOrderParams, {}, orderBookApiMock) + const result = await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) expect(result.orderToSign.feeAmount).toBe('0') }) it('Should add appDataKeccak256 to the order', async () => { - const result = await getQuote(defaultOrderParams, {}, orderBookApiMock) + const result = await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) expect(result.orderToSign.appData.length).toBe(2 + 64) }) diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index 91633689..e420cb71 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -1,4 +1,11 @@ -import { AppDataInfo, SwapAdvancedSettings, SwapParameters } from './types' +import { + AccountAddress, + AppDataInfo, + SwapAdvancedSettings, + SwapParameters, + TradeParameters, + TraderParameters, +} from './types' import { DEFAULT_QUOTE_VALIDITY, log } from './consts' import { @@ -20,23 +27,23 @@ import { Signer } from 'ethers' import { WRAPPED_NATIVE_CURRENCIES } from '../common' export interface QuoteResults { - swapParameters: SwapParameters + tradeParameters: TradeParameters amountsAndCosts: QuoteAmountsAndCosts orderToSign: UnsignedOrder quoteResponse: OrderQuoteResponse appDataInfo: AppDataInfo orderBookApi: OrderBookApi - signer: Signer } +export type QuoteResultsWithSigner = QuoteResults & { signer: Signer } + export async function getQuote( - swapParameters: SwapParameters, + tradeParameters: TradeParameters, + trader: Omit & { account: AccountAddress }, advancedSettings?: SwapAdvancedSettings, _orderBookApi?: OrderBookApi ): Promise { const { - appCode, - chainId, sellToken, sellTokenDecimals, buyToken, @@ -47,15 +54,15 @@ export async function getQuote( validFor = DEFAULT_QUOTE_VALIDITY, slippageBps = 0, env = 'prod', - } = swapParameters + } = tradeParameters + + const { appCode, chainId, account: from } = trader log(`Swap ${amount} ${sellToken} for ${buyToken} on chain ${chainId}`) - const signer = getSigner(swapParameters.signer) const orderBookApi = _orderBookApi || new OrderBookApi({ chainId, env }) - const from = await signer.getAddress() - const receiver = swapParameters.receiver || from + const receiver = tradeParameters.receiver || from const isSell = kind === 'sell' log('Building app data...') @@ -73,7 +80,7 @@ export async function getQuote( const quoteRequest: OrderQuoteRequest = { from, - sellToken: getIsEthFlowOrder(swapParameters) ? WRAPPED_NATIVE_CURRENCIES[chainId] : sellToken, + sellToken: getIsEthFlowOrder(tradeParameters) ? WRAPPED_NATIVE_CURRENCIES[chainId] : sellToken, buyToken, receiver, validFor, @@ -101,9 +108,30 @@ export async function getQuote( const orderToSign = getOrderToSign( { from, networkCostsAmount: quoteResponse.quote.feeAmount }, - swapParamsToLimitOrderParams(swapParameters, quoteResponse), + swapParamsToLimitOrderParams(tradeParameters, quoteResponse), appDataInfo.appDataKeccak256 ) - return { amountsAndCosts, quoteResponse, appDataInfo, orderBookApi, signer, orderToSign, swapParameters } + return { amountsAndCosts, quoteResponse, appDataInfo, orderBookApi, orderToSign, tradeParameters: tradeParameters } +} + +export async function getQuoteWithSigner( + swapParameters: SwapParameters, + advancedSettings?: SwapAdvancedSettings, + orderBookApi?: OrderBookApi +): Promise { + const signer = getSigner(swapParameters.signer) + + const trader = { + chainId: swapParameters.chainId, + appCode: swapParameters.appCode, + account: (await signer.getAddress()) as AccountAddress, + } + + const result = await getQuote(swapParameters, trader, advancedSettings, orderBookApi) + + return { + ...result, + signer, + } } diff --git a/src/trading/index.ts b/src/trading/index.ts index 84835277..7439dd7b 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -4,7 +4,7 @@ export * from './tradingSdk' /** * Main trading functions */ -export { getQuote } from './getQuote' +export { getQuote, getQuoteWithSigner } from './getQuote' export { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' export { postLimitOrder } from './postLimitOrder' export { postCoWProtocolTrade } from './postCoWProtocolTrade' diff --git a/src/trading/postCoWProtocolTrade.test.ts b/src/trading/postCoWProtocolTrade.test.ts index 59a1f00e..2f4f7ad7 100644 --- a/src/trading/postCoWProtocolTrade.test.ts +++ b/src/trading/postCoWProtocolTrade.test.ts @@ -54,6 +54,7 @@ const currentTimestamp = 1487076708000 const signatureMock = { signature: '0x000a1', signingScheme: 'eip712' } const signer = new VoidSigner('0x21c3de23d98caddc406e3d31b25e807addf33333') +signer.getChainId = jest.fn().mockResolvedValue(SupportedChainId.GNOSIS_CHAIN) const sendOrderMock = jest.fn() const orderBookApiMock = { diff --git a/src/trading/postCoWProtocolTrade.ts b/src/trading/postCoWProtocolTrade.ts index 5f4b59bd..06faad4f 100644 --- a/src/trading/postCoWProtocolTrade.ts +++ b/src/trading/postCoWProtocolTrade.ts @@ -1,6 +1,6 @@ import { OrderBookApi, OrderCreation } from '../order-book' import type { Signer } from 'ethers' -import { AppDataInfo, LimitOrderParameters } from './types' +import { AppDataInfo, LimitTradeParameters } from './types' import { log, SIGN_SCHEME_MAP } from './consts' import { OrderSigningUtils } from '../order-signing' import { getOrderToSign } from './getOrderToSign' @@ -11,7 +11,7 @@ export async function postCoWProtocolTrade( orderBookApi: OrderBookApi, signer: Signer, appData: AppDataInfo, - params: LimitOrderParameters, + params: LimitTradeParameters, networkCostsAmount = '0' ): Promise { if (getIsEthFlowOrder(params)) { @@ -20,9 +20,10 @@ export async function postCoWProtocolTrade( return orderId } - const { chainId, quoteId = null } = params + const { quoteId = null } = params const { appDataKeccak256, fullAppData } = appData + const chainId = await signer.getChainId() const from = await signer.getAddress() const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appData.appDataKeccak256) diff --git a/src/trading/postOnChainTrade.test.ts b/src/trading/postOnChainTrade.test.ts index 963e138c..b64e3170 100644 --- a/src/trading/postOnChainTrade.test.ts +++ b/src/trading/postOnChainTrade.test.ts @@ -47,6 +47,7 @@ const defaultOrderParams: LimitOrderParameters = { const account = '0x21c3de23d98caddc406e3d31b25e807addf33333' const signer = new VoidSigner(account) +signer.getChainId = jest.fn().mockResolvedValue(SupportedChainId.GNOSIS_CHAIN) const currentTimestamp = 1487076708000 diff --git a/src/trading/postOnChainTrade.ts b/src/trading/postOnChainTrade.ts index 36da2241..12ab984b 100644 --- a/src/trading/postOnChainTrade.ts +++ b/src/trading/postOnChainTrade.ts @@ -1,5 +1,5 @@ import { Signer } from 'ethers' -import { AppDataInfo, LimitOrderParameters } from './types' +import { AppDataInfo, LimitTradeParameters } from './types' import { calculateUniqueOrderId, EthFlowOrderExistsCallback } from './calculateUniqueOrderId' import { getOrderToSign } from './getOrderToSign' import { type EthFlow, EthFlow__factory } from '../common/generated' @@ -12,13 +12,14 @@ export async function postOnChainTrade( orderBookApi: OrderBookApi, signer: Signer, appData: Pick, - params: LimitOrderParameters, + params: LimitTradeParameters, networkCostsAmount = '0', checkEthFlowOrderExists?: EthFlowOrderExistsCallback ): Promise<{ txHash: string; orderId: string }> { - const { chainId, quoteId } = params + const { quoteId } = params const { appDataKeccak256, fullAppData } = appData + const chainId = await signer.getChainId() const from = await signer.getAddress() const contract = getEthFlowContract(chainId, signer, params.env) diff --git a/src/trading/postSwapOrder.ts b/src/trading/postSwapOrder.ts index b5ffd6e9..ba49fd46 100644 --- a/src/trading/postSwapOrder.ts +++ b/src/trading/postSwapOrder.ts @@ -1,11 +1,11 @@ import { SwapAdvancedSettings, SwapParameters } from './types' import { postCoWProtocolTrade } from './postCoWProtocolTrade' -import { getQuote, QuoteResults } from './getQuote' +import { getQuoteWithSigner, QuoteResultsWithSigner } from './getQuote' import { swapParamsToLimitOrderParams } from './utils' export async function postSwapOrder(params: SwapParameters, advancedSettings?: SwapAdvancedSettings) { - return postSwapOrderFromQuote(await getQuote(params, advancedSettings)) + return postSwapOrderFromQuote(await getQuoteWithSigner(params, advancedSettings)) } export async function postSwapOrderFromQuote({ @@ -13,13 +13,13 @@ export async function postSwapOrderFromQuote({ signer, appDataInfo, quoteResponse, - swapParameters, -}: QuoteResults): Promise { + tradeParameters, +}: QuoteResultsWithSigner): Promise { return postCoWProtocolTrade( orderBookApi, signer, appDataInfo, - swapParamsToLimitOrderParams(swapParameters, quoteResponse), + swapParamsToLimitOrderParams(tradeParameters, quoteResponse), quoteResponse.quote.feeAmount ) } diff --git a/src/trading/tradingSdk.ts b/src/trading/tradingSdk.ts index 83ce60b3..c0cc5946 100644 --- a/src/trading/tradingSdk.ts +++ b/src/trading/tradingSdk.ts @@ -8,7 +8,7 @@ import { } from './types' import { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' import { postLimitOrder } from './postLimitOrder' -import { getQuote } from './getQuote' +import { getQuoteWithSigner } from './getQuote' import { postOnChainTrade } from './postOnChainTrade' import { swapParamsToLimitOrderParams } from './utils' @@ -24,18 +24,18 @@ export class TradingSdk { } async postOnChainTrade(params: TradeParameters, advancedSettings?: SwapAdvancedSettings) { - const quoteResults = await getQuote(this.mergeParams(params), advancedSettings) + const quoteResults = await getQuoteWithSigner(this.mergeParams(params), advancedSettings) return postOnChainTrade( quoteResults.orderBookApi, quoteResults.signer, quoteResults.appDataInfo, - swapParamsToLimitOrderParams(quoteResults.swapParameters, quoteResults.quoteResponse) + swapParamsToLimitOrderParams(quoteResults.tradeParameters, quoteResults.quoteResponse) ) } async getQuote(params: TradeParameters, advancedSettings?: SwapAdvancedSettings): Promise { - const quoteResults = await getQuote(this.mergeParams(params), advancedSettings) + const quoteResults = await getQuoteWithSigner(this.mergeParams(params), advancedSettings) return { quoteResults, diff --git a/src/trading/types.ts b/src/trading/types.ts index a577a1de..d21ed9cc 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -5,6 +5,9 @@ import { CowEnv, SupportedChainId } from '../common' import { QuoteResults } from './getQuote' import type { ExternalProvider } from '@ethersproject/providers' +export type PrivateKey = string // 64 characters +export type AccountAddress = `0x${string}` // 42 characters + export interface TradeBaseParameters { kind: OrderKind sellToken: Address @@ -25,13 +28,13 @@ export interface TradeOptionalParameters { export interface TraderParameters { chainId: SupportedChainId - signer: Signer | ExternalProvider | string appCode: string + signer: Signer | ExternalProvider | PrivateKey } export interface TradeParameters extends TradeBaseParameters, TradeOptionalParameters {} -export interface SwapParameters extends TraderParameters, TradeParameters {} +export interface SwapParameters extends TradeParameters, TraderParameters {} export interface LimitTradeParameters extends Omit { sellAmount: string diff --git a/src/trading/utils.ts b/src/trading/utils.ts index 8ca9f9f0..c31120f9 100644 --- a/src/trading/utils.ts +++ b/src/trading/utils.ts @@ -1,13 +1,13 @@ -import { LimitOrderParameters, SwapParameters, TraderParameters } from './types' +import { AccountAddress, LimitTradeParameters, PrivateKey, TradeParameters } from './types' import { OrderQuoteResponse } from '../order-book' import { ETH_ADDRESS } from '../common' import { ethers, Signer } from 'ethers' -import { Web3Provider } from '@ethersproject/providers' +import { type ExternalProvider, Web3Provider } from '@ethersproject/providers' export function swapParamsToLimitOrderParams( - params: SwapParameters, + params: TradeParameters, { quote: { sellAmount, buyAmount }, id }: OrderQuoteResponse -): LimitOrderParameters { +): LimitTradeParameters { // In this SDK we always use Optimal quotes which are always have id // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return { ...params, sellAmount, buyAmount, quoteId: id! } @@ -17,7 +17,7 @@ export function getIsEthFlowOrder(params: { sellToken: string }): boolean { return params.sellToken.toLowerCase() === ETH_ADDRESS.toLowerCase() } -export function getSigner(signer: TraderParameters['signer']): Signer { +export function getSigner(signer: Signer | ExternalProvider | PrivateKey): Signer { if (typeof signer === 'string') return new ethers.Wallet(signer) if ('request' in signer || 'send' in signer) { @@ -28,3 +28,7 @@ export function getSigner(signer: TraderParameters['signer']): Signer { return signer as Signer } + +export function isAccountAddress(address: any): address is AccountAddress { + return typeof address === 'string' && /^0x[0-9a-fA-F]{40}$/.test(address) +} From a054c436ff5f424d1b7a848d58d15523901fc13b Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 19 Nov 2024 13:38:25 +0500 Subject: [PATCH 30/67] chore: rc --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d8541f73..0aa4078f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "5.8.0-RC.0", + "version": "5.8.0-RC.1", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" From b878eb11aa7b541db6ad1a5fdec5e0f51cfd7925 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 19 Nov 2024 13:45:35 +0500 Subject: [PATCH 31/67] chore: move QuoteResults to types --- src/trading/getQuote.ts | 14 +------------- src/trading/types.ts | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index e420cb71..8a007a89 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -1,6 +1,6 @@ import { AccountAddress, - AppDataInfo, + QuoteResults, SwapAdvancedSettings, SwapParameters, TradeParameters, @@ -12,29 +12,17 @@ import { getQuoteAmountsAndCosts, OrderBookApi, OrderQuoteRequest, - OrderQuoteResponse, OrderQuoteSideKindBuy, OrderQuoteSideKindSell, PriceQuality, - QuoteAmountsAndCosts, SigningScheme, } from '../order-book' import { buildAppData } from './appDataUtils' -import { UnsignedOrder } from '../order-signing' import { getOrderToSign } from './getOrderToSign' import { getIsEthFlowOrder, getSigner, swapParamsToLimitOrderParams } from './utils' import { Signer } from 'ethers' import { WRAPPED_NATIVE_CURRENCIES } from '../common' -export interface QuoteResults { - tradeParameters: TradeParameters - amountsAndCosts: QuoteAmountsAndCosts - orderToSign: UnsignedOrder - quoteResponse: OrderQuoteResponse - appDataInfo: AppDataInfo - orderBookApi: OrderBookApi -} - export type QuoteResultsWithSigner = QuoteResults & { signer: Signer } export async function getQuote( diff --git a/src/trading/types.ts b/src/trading/types.ts index d21ed9cc..e7049aaa 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -1,9 +1,16 @@ -import { latest, LatestAppDataDocVersion, AppDataParams } from '@cowprotocol/app-data' -import { Address, OrderQuoteRequest, OrderKind } from '../order-book' +import type { AppDataParams, latest, LatestAppDataDocVersion } from '@cowprotocol/app-data' +import type { + Address, + OrderBookApi, + OrderKind, + OrderQuoteRequest, + OrderQuoteResponse, + QuoteAmountsAndCosts, +} from '../order-book' import type { Signer } from '@ethersproject/abstract-signer' -import { CowEnv, SupportedChainId } from '../common' -import { QuoteResults } from './getQuote' +import type { CowEnv, SupportedChainId } from '../common' import type { ExternalProvider } from '@ethersproject/providers' +import type { UnsignedOrder } from '../order-signing' export type PrivateKey = string // 64 characters export type AccountAddress = `0x${string}` // 42 characters @@ -54,6 +61,15 @@ export interface LimitOrderAdvancedSettings { appData?: AppDataParams } +export interface QuoteResults { + tradeParameters: TradeParameters + amountsAndCosts: QuoteAmountsAndCosts + orderToSign: UnsignedOrder + quoteResponse: OrderQuoteResponse + appDataInfo: AppDataInfo + orderBookApi: OrderBookApi +} + export interface QuoteAndPost { quoteResults: QuoteResults postSwapOrderFromQuote(): Promise From e99875c905c9e398a77c8706f1b62de913f8ae03 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 19 Nov 2024 15:42:59 +0500 Subject: [PATCH 32/67] refactor: make QuoteResults serializable --- package.json | 6 ++++-- src/trading/getQuote.test.ts | 12 ++++++------ src/trading/getQuote.ts | 16 +++++++++++----- src/trading/postSwapOrder.ts | 5 +---- src/trading/tradingSdk.ts | 8 ++++---- src/trading/types.ts | 10 +--------- 6 files changed, 27 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 0aa4078f..c0e20349 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "prepublishOnly": "npm test && npm run lint", "graphql:codegen": "graphql-codegen --config graphql-codegen.yml", "swagger:codegen": " openapi --input https://raw.githubusercontent.com/cowprotocol/services/main/crates/orderbook/openapi.yml --output src/order-book/generated --exportServices false --exportCore false", - "typechain:codegen": "typechain --target ethers-v5 --out-dir ./src/common/generated './abi/*.json'" + "typechain:codegen": "typechain --target ethers-v5 --out-dir ./src/common/generated './abi/*.json'", + "trading:generateSchemas": "ts-node scripts/generateTradingSchemas.ts" }, "dependencies": { "@cowprotocol/app-data": "^2.1.0", @@ -54,7 +55,7 @@ "@graphql-codegen/typescript-operations": "^3.0.0", "@typechain/ethers-v5": "^11.0.0", "@types/jest": "^29.4.0", - "@types/node": "^18.13.0", + "@types/node": "^22.9.0", "@typescript-eslint/eslint-plugin": "^5.51.0", "@typescript-eslint/parser": "^5.51.0", "babel-plugin-inline-import": "^3.0.0", @@ -69,6 +70,7 @@ "microbundle": "^0.15.1", "openapi-typescript-codegen": "^0.23.0", "prettier": "^2.5.1", + "ts-json-schema-generator": "^2.3.0", "ts-mockito": "^2.6.1", "tsc-watch": "^6.0.0", "typechain": "^8.2.0", diff --git a/src/trading/getQuote.test.ts b/src/trading/getQuote.test.ts index c2596e7e..666a3118 100644 --- a/src/trading/getQuote.test.ts +++ b/src/trading/getQuote.test.ts @@ -65,7 +65,7 @@ describe('getQuoteToSign', () => { describe('App data', () => { it('Should add slippageBps and appCode from parameters', async () => { - const result = await getQuoteWithSigner({ ...defaultOrderParams, slippageBps: 76 }, {}, orderBookApiMock) + const { result } = await getQuoteWithSigner({ ...defaultOrderParams, slippageBps: 76 }, {}, orderBookApiMock) const appData = JSON.parse(result.appDataInfo.fullAppData) expect(appData.metadata.quote.slippageBips).toBe(76) @@ -73,7 +73,7 @@ describe('getQuoteToSign', () => { }) it('Should add advanced appData parameters', async () => { - const result = await getQuoteWithSigner( + const { result } = await getQuoteWithSigner( defaultOrderParams, { appData: { @@ -138,7 +138,7 @@ describe('getQuoteToSign', () => { describe('Amounts and costs', () => { it('Should take slippage value into account', async () => { - const result = await getQuoteWithSigner({ ...defaultOrderParams, slippageBps: 20 }, {}, orderBookApiMock) + const { result } = await getQuoteWithSigner({ ...defaultOrderParams, slippageBps: 20 }, {}, orderBookApiMock) const buyAmount = quoteResponseMock.quote.buyAmount expect(+result.amountsAndCosts.afterSlippage.buyAmount.toString()).toBe( @@ -146,7 +146,7 @@ describe('getQuoteToSign', () => { ) }) it('Should calculate network costs based on quote API response', async () => { - const result = await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) + const { result } = await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) expect(result.amountsAndCosts.costs.networkFee.amountInSellCurrency.toString()).toBe( quoteResponseMock.quote.feeAmount @@ -156,12 +156,12 @@ describe('getQuoteToSign', () => { describe('Order to sign', () => { it('feeAmount should always be zero', async () => { - const result = await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) + const { result } = await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) expect(result.orderToSign.feeAmount).toBe('0') }) it('Should add appDataKeccak256 to the order', async () => { - const result = await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) + const { result } = await getQuoteWithSigner(defaultOrderParams, {}, orderBookApiMock) expect(result.orderToSign.appData.length).toBe(2 + 64) }) diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index 8a007a89..afa2ee9d 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -23,14 +23,14 @@ import { getIsEthFlowOrder, getSigner, swapParamsToLimitOrderParams } from './ut import { Signer } from 'ethers' import { WRAPPED_NATIVE_CURRENCIES } from '../common' -export type QuoteResultsWithSigner = QuoteResults & { signer: Signer } +export type QuoteResultsWithSigner = { result: QuoteResults & { signer: Signer }; orderBookApi: OrderBookApi } export async function getQuote( tradeParameters: TradeParameters, trader: Omit & { account: AccountAddress }, advancedSettings?: SwapAdvancedSettings, _orderBookApi?: OrderBookApi -): Promise { +): Promise<{ result: QuoteResults; orderBookApi: OrderBookApi }> { const { sellToken, sellTokenDecimals, @@ -100,7 +100,10 @@ export async function getQuote( appDataInfo.appDataKeccak256 ) - return { amountsAndCosts, quoteResponse, appDataInfo, orderBookApi, orderToSign, tradeParameters: tradeParameters } + return { + result: { amountsAndCosts, quoteResponse, appDataInfo, orderToSign, tradeParameters: tradeParameters }, + orderBookApi, + } } export async function getQuoteWithSigner( @@ -119,7 +122,10 @@ export async function getQuoteWithSigner( const result = await getQuote(swapParameters, trader, advancedSettings, orderBookApi) return { - ...result, - signer, + result: { + ...result.result, + signer, + }, + orderBookApi: result.orderBookApi, } } diff --git a/src/trading/postSwapOrder.ts b/src/trading/postSwapOrder.ts index ba49fd46..386e8e47 100644 --- a/src/trading/postSwapOrder.ts +++ b/src/trading/postSwapOrder.ts @@ -10,10 +10,7 @@ export async function postSwapOrder(params: SwapParameters, advancedSettings?: S export async function postSwapOrderFromQuote({ orderBookApi, - signer, - appDataInfo, - quoteResponse, - tradeParameters, + result: { signer, appDataInfo, quoteResponse, tradeParameters }, }: QuoteResultsWithSigner): Promise { return postCoWProtocolTrade( orderBookApi, diff --git a/src/trading/tradingSdk.ts b/src/trading/tradingSdk.ts index c0cc5946..874c93a9 100644 --- a/src/trading/tradingSdk.ts +++ b/src/trading/tradingSdk.ts @@ -28,9 +28,9 @@ export class TradingSdk { return postOnChainTrade( quoteResults.orderBookApi, - quoteResults.signer, - quoteResults.appDataInfo, - swapParamsToLimitOrderParams(quoteResults.tradeParameters, quoteResults.quoteResponse) + quoteResults.result.signer, + quoteResults.result.appDataInfo, + swapParamsToLimitOrderParams(quoteResults.result.tradeParameters, quoteResults.result.quoteResponse) ) } @@ -38,7 +38,7 @@ export class TradingSdk { const quoteResults = await getQuoteWithSigner(this.mergeParams(params), advancedSettings) return { - quoteResults, + quoteResults: quoteResults.result, postSwapOrderFromQuote: () => postSwapOrderFromQuote(quoteResults), } } diff --git a/src/trading/types.ts b/src/trading/types.ts index e7049aaa..a7c4a4e6 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -1,12 +1,5 @@ import type { AppDataParams, latest, LatestAppDataDocVersion } from '@cowprotocol/app-data' -import type { - Address, - OrderBookApi, - OrderKind, - OrderQuoteRequest, - OrderQuoteResponse, - QuoteAmountsAndCosts, -} from '../order-book' +import type { Address, OrderKind, OrderQuoteRequest, OrderQuoteResponse, QuoteAmountsAndCosts } from '../order-book' import type { Signer } from '@ethersproject/abstract-signer' import type { CowEnv, SupportedChainId } from '../common' import type { ExternalProvider } from '@ethersproject/providers' @@ -67,7 +60,6 @@ export interface QuoteResults { orderToSign: UnsignedOrder quoteResponse: OrderQuoteResponse appDataInfo: AppDataInfo - orderBookApi: OrderBookApi } export interface QuoteAndPost { From 18ad494c86995d5d5b01fcaf5763e7f7ec0b394e Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 19 Nov 2024 15:43:59 +0500 Subject: [PATCH 33/67] feat: add json schemas for trading entities --- .eslintrc.json | 2 +- package.json | 2 +- scripts/generateTradingSchemas.ts | 30 +++++ src/trading/getQuote.ts | 4 +- src/trading/types.ts | 10 ++ yarn.lock | 216 +++++++++++++++++++++++++++++- 6 files changed, 255 insertions(+), 9 deletions(-) create mode 100644 scripts/generateTradingSchemas.ts diff --git a/.eslintrc.json b/.eslintrc.json index b241b332..c227a5a1 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -22,5 +22,5 @@ ] }, - "ignorePatterns": ["dist", "node_modules", "src/subgraph/graphql.ts", "examples"] + "ignorePatterns": ["dist", "node_modules", "src/subgraph/graphql.ts", "examples", "schemas"] } diff --git a/package.json b/package.json index c0e20349..9f321491 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "prebuild": "rm -rf dist && yarn run codegen", "build": "microbundle -f modern,esm,cjs", "start": "microbundle -f modern,esm,cjs watch", - "postbuild": "cp package.json dist && cp README.md dist", + "postbuild": "cp package.json dist && cp README.md dist && npm run trading:generateSchemas", "lint": "eslint src", "format": "prettier --write \"src/**/*.+(ts|json)\"", "test": "jest", diff --git a/scripts/generateTradingSchemas.ts b/scripts/generateTradingSchemas.ts new file mode 100644 index 00000000..e358192e --- /dev/null +++ b/scripts/generateTradingSchemas.ts @@ -0,0 +1,30 @@ +import { Config, createGenerator } from 'ts-json-schema-generator' +import { writeFileSync, mkdirSync } from 'fs' + +const config: Config = { + path: 'src/trading/types.ts', + expose: 'none', + topRef: false, +} + +const types = [ + 'QuoterParameters', + 'TradeParameters', + 'LimitTradeParameters', + 'SwapAdvancedSettings', + 'LimitOrderAdvancedSettings', + 'QuoteResultsSerialized', +] + +const outputPath = 'dist/schemas/trading/' + +const generator = createGenerator(config) + +mkdirSync(outputPath, { recursive: true }) + +types.forEach((type) => { + const schema = generator.createSchema(type) + const schemaString = JSON.stringify(schema, null, 2) + + writeFileSync(outputPath + `${type}.ts`, `export default ${schemaString} as const`) +}) diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index afa2ee9d..52afc706 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -1,10 +1,10 @@ import { AccountAddress, QuoteResults, + QuoterParameters, SwapAdvancedSettings, SwapParameters, TradeParameters, - TraderParameters, } from './types' import { DEFAULT_QUOTE_VALIDITY, log } from './consts' @@ -27,7 +27,7 @@ export type QuoteResultsWithSigner = { result: QuoteResults & { signer: Signer } export async function getQuote( tradeParameters: TradeParameters, - trader: Omit & { account: AccountAddress }, + trader: QuoterParameters, advancedSettings?: SwapAdvancedSettings, _orderBookApi?: OrderBookApi ): Promise<{ result: QuoteResults; orderBookApi: OrderBookApi }> { diff --git a/src/trading/types.ts b/src/trading/types.ts index a7c4a4e6..ebdd6831 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -32,6 +32,8 @@ export interface TraderParameters { signer: Signer | ExternalProvider | PrivateKey } +export type QuoterParameters = Omit & { account: AccountAddress } + export interface TradeParameters extends TradeBaseParameters, TradeOptionalParameters {} export interface SwapParameters extends TradeParameters, TraderParameters {} @@ -62,6 +64,14 @@ export interface QuoteResults { appDataInfo: AppDataInfo } +export interface QuoteResultsSerialized { + tradeParameters: TradeParameters + amountsAndCosts: QuoteAmountsAndCosts + orderToSign: UnsignedOrder + quoteResponse: OrderQuoteResponse + appDataInfo: AppDataInfo +} + export interface QuoteAndPost { quoteResults: QuoteResults postSwapOrderFromQuote(): Promise diff --git a/yarn.lock b/yarn.lock index daa5d44f..cd4dfbe9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2573,6 +2573,18 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -2965,6 +2977,11 @@ tslib "^2.5.0" webcrypto-core "^1.7.7" +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -3258,6 +3275,11 @@ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138" integrity sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA== +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -3290,10 +3312,12 @@ dependencies: undici-types "~5.26.4" -"@types/node@^18.13.0": - version "18.13.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.13.0.tgz#0400d1e6ce87e9d3032c19eb6c58205b0d3f7850" - integrity sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg== +"@types/node@^22.9.0": + version "22.9.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.0.tgz#b7f16e5c3384788542c72dc3d561a7ceae2c0365" + integrity sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ== + dependencies: + undici-types "~6.19.8" "@types/normalize-package-data@^2.4.0": version "2.4.4" @@ -3559,6 +3583,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -3583,6 +3612,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -4353,6 +4387,11 @@ command-line-usage@^6.1.0: table-layout "^1.0.2" typical "^5.2.0" +commander@^12.0.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -4472,6 +4511,15 @@ cross-fetch@^3.0.4, cross-fetch@^3.1.5: dependencies: node-fetch "2.6.7" +cross-spawn@^7.0.0: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -4763,6 +4811,11 @@ duplexer@^0.1.1, duplexer@^0.1.2, duplexer@~0.1.1: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -4816,6 +4869,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -5390,6 +5448,14 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +foreground-child@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" + integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -5562,6 +5628,18 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^10.3.12: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -6395,6 +6473,15 @@ it-parallel-batch@^1.0.9: dependencies: it-batch "^1.0.9" +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jake@^10.8.5: version "10.8.5" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46" @@ -6945,7 +7032,7 @@ json-to-pretty-yaml@^1.2.2: remedial "^1.0.7" remove-trailing-spaces "^1.0.6" -json5@^2.2.0, json5@^2.2.2: +json5@^2.2.0, json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -7153,6 +7240,11 @@ lower-case@^2.0.2: dependencies: tslib "^2.0.3" +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -7377,6 +7469,13 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -7391,6 +7490,11 @@ minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" @@ -7746,6 +7850,11 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + param-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" @@ -7833,6 +7942,14 @@ path-root@^0.1.1: dependencies: path-root-regex "^0.1.0" +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -8689,6 +8806,11 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" +safe-stable-stringify@^2.4.3: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -8795,6 +8917,11 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + signedsource@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a" @@ -8989,6 +9116,15 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -8998,6 +9134,15 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string.prototype.matchall@^4.0.6: version "4.0.8" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" @@ -9037,6 +9182,13 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" @@ -9051,6 +9203,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" @@ -9248,6 +9407,20 @@ ts-essentials@^7.0.1: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== +ts-json-schema-generator@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/ts-json-schema-generator/-/ts-json-schema-generator-2.3.0.tgz#d533027cdb13b625acba0a3e931a4ba88f0e44ad" + integrity sha512-t4lBQAwZc0sOJq9LJt3NgbznIcslVnm0JeEMFq8qIRklpMRY8jlYD0YmnRWbqBKANxkby91P1XanSSlSOFpUmg== + dependencies: + "@types/json-schema" "^7.0.15" + commander "^12.0.0" + glob "^10.3.12" + json5 "^2.2.3" + normalize-path "^3.0.0" + safe-stable-stringify "^2.4.3" + tslib "^2.6.2" + typescript "^5.4.5" + ts-log@^2.2.3: version "2.2.5" resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.2.5.tgz#aef3252f1143d11047e2cb6f7cfaac7408d96623" @@ -9304,6 +9477,11 @@ tslib@^2.0.3, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@^2.6.2: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tslib@~2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" @@ -9400,6 +9578,11 @@ typescript@^4.1.3, typescript@^4.9.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +typescript@^5.4.5: + version "5.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== + typical@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" @@ -9454,6 +9637,11 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.19.8: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" @@ -9703,6 +9891,15 @@ wordwrapjs@^4.0.0: reduce-flatten "^2.0.0" typical "^5.2.0" +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -9721,6 +9918,15 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From 16d7bd2904655bb6757cfb2b24f18be5120b9dad Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 20 Nov 2024 12:40:34 +0500 Subject: [PATCH 34/67] chore: rc --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9f321491..c7fff6d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "5.8.0-RC.1", + "version": "5.8.0-RC.2", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" From f5af9bd21df1154b5e0f167812e209bab0820b54 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 20 Nov 2024 12:45:25 +0500 Subject: [PATCH 35/67] chore: up node v --- .github/workflows/build.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 75e04ac3..ee4cd78b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ on: types: [published] env: - NODE_VERSION: lts/gallium + NODE_VERSION: lts/hydrogen jobs: build: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5f00a753..21963f31 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -5,7 +5,7 @@ on: types: [published] env: - NODE_VERSION: lts/gallium + NODE_VERSION: lts/hydrogen jobs: deploy: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2823405e..2b8758de 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,7 @@ name: Unit tests & Coverage on: [push, pull_request] env: - NODE_VERSION: lts/gallium + NODE_VERSION: lts/hydrogen COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} jobs: From 899fb0fd407ed680d6d97e3c663359a4fcd93e18 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 20 Nov 2024 12:51:33 +0500 Subject: [PATCH 36/67] chore: remove schema gen call --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c7fff6d4..3ca89577 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "prebuild": "rm -rf dist && yarn run codegen", "build": "microbundle -f modern,esm,cjs", "start": "microbundle -f modern,esm,cjs watch", - "postbuild": "cp package.json dist && cp README.md dist && npm run trading:generateSchemas", + "postbuild": "cp package.json dist && cp README.md dist", "lint": "eslint src", "format": "prettier --write \"src/**/*.+(ts|json)\"", "test": "jest", From d4a0a1b147e2dccfb5a1cbebb34e4533c46d4fd5 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 22 Nov 2024 13:17:40 +0500 Subject: [PATCH 37/67] chore: up app-data version --- package.json | 6 +++--- yarn.lock | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 3ca89577..e3f40d19 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "prebuild": "rm -rf dist && yarn run codegen", "build": "microbundle -f modern,esm,cjs", "start": "microbundle -f modern,esm,cjs watch", - "postbuild": "cp package.json dist && cp README.md dist", + "postbuild": "cp package.json dist && cp README.md dist && yarn run trading:generateSchemas", "lint": "eslint src", "format": "prettier --write \"src/**/*.+(ts|json)\"", "test": "jest", @@ -27,12 +27,12 @@ "prepare": "npm run build", "prepublishOnly": "npm test && npm run lint", "graphql:codegen": "graphql-codegen --config graphql-codegen.yml", - "swagger:codegen": " openapi --input https://raw.githubusercontent.com/cowprotocol/services/main/crates/orderbook/openapi.yml --output src/order-book/generated --exportServices false --exportCore false", + "swagger:codegen": " openapi --input https://raw.githubusercontent.com/cowprotocol/services/v2.285.0/crates/orderbook/openapi.yml --output src/order-book/generated --exportServices false --exportCore false", "typechain:codegen": "typechain --target ethers-v5 --out-dir ./src/common/generated './abi/*.json'", "trading:generateSchemas": "ts-node scripts/generateTradingSchemas.ts" }, "dependencies": { - "@cowprotocol/app-data": "^2.1.0", + "@cowprotocol/app-data": "^2.4.0", "@cowprotocol/contracts": "^1.6.0", "@ethersproject/abstract-signer": "^5.7.0", "@openzeppelin/merkle-tree": "^1.0.5", diff --git a/yarn.lock b/yarn.lock index cd4dfbe9..f8820f4c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1766,10 +1766,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@cowprotocol/app-data@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@cowprotocol/app-data/-/app-data-2.1.0.tgz#55c95e7ffd3fb0dcfecd0fc64a4273955d1d63d1" - integrity sha512-gOlQxng7X5/aQoz2Eg27OegyKgpZVhOEdUQ9cUsc4OnSPal8F4tmLqefKQQWm4Ktaolk7zzh0kiL1vhWxvszmQ== +"@cowprotocol/app-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@cowprotocol/app-data/-/app-data-2.4.0.tgz#326e20065161e06308cf0ff429fe9dd2908c1c30" + integrity sha512-aG3CicUdR7jpY5/linxXmpL4axmiUvEwiHlOM0qKO/QdbNSntKNXjSu3r4QtHZ7BUiF1VUkcDVvvFW4D2MA0Rw== dependencies: ajv "^8.11.0" cross-fetch "^3.1.5" From 45d5e9606399703b4810fa12d996ff8dd42b51a3 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 22 Nov 2024 13:24:14 +0500 Subject: [PATCH 38/67] chore: bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e3f40d19..d47853fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "5.8.0-RC.2", + "version": "5.8.0-RC.3", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" From 31916779f454a01b0872a01dde62c3bb9c2bddcd Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 22 Nov 2024 16:15:49 +0500 Subject: [PATCH 39/67] feat: add order typed data to quote results --- package.json | 2 +- src/trading/getOrderTypedData.ts | 20 ++++++++++++++++++++ src/trading/getQuote.ts | 5 ++++- src/trading/types.ts | 30 +++++++++++++++++++++++++----- 4 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 src/trading/getOrderTypedData.ts diff --git a/package.json b/package.json index d47853fe..83b22600 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "5.8.0-RC.3", + "version": "5.8.0-RC.4", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" diff --git a/src/trading/getOrderTypedData.ts b/src/trading/getOrderTypedData.ts new file mode 100644 index 00000000..3edc9f2f --- /dev/null +++ b/src/trading/getOrderTypedData.ts @@ -0,0 +1,20 @@ +import { ORDER_TYPE_FIELDS } from '@cowprotocol/contracts' +import { ORDER_PRIMARY_TYPE, OrderTypedData } from './types' +import { OrderSigningUtils, UnsignedOrder } from '../order-signing' +import { SupportedChainId } from '../common' + +export async function getOrderTypedData( + chainId: SupportedChainId, + orderToSign: UnsignedOrder +): Promise { + const domain = (await OrderSigningUtils.getDomain(chainId)) as OrderTypedData['domain'] + + return { + domain, + primaryType: ORDER_PRIMARY_TYPE, + types: { + [ORDER_PRIMARY_TYPE]: ORDER_TYPE_FIELDS, + }, + message: orderToSign, + } +} diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index 52afc706..b5bd08e5 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -22,6 +22,7 @@ import { getOrderToSign } from './getOrderToSign' import { getIsEthFlowOrder, getSigner, swapParamsToLimitOrderParams } from './utils' import { Signer } from 'ethers' import { WRAPPED_NATIVE_CURRENCIES } from '../common' +import { getOrderTypedData } from './getOrderTypedData' export type QuoteResultsWithSigner = { result: QuoteResults & { signer: Signer }; orderBookApi: OrderBookApi } @@ -100,8 +101,10 @@ export async function getQuote( appDataInfo.appDataKeccak256 ) + const orderTypedData = await getOrderTypedData(chainId, orderToSign) + return { - result: { amountsAndCosts, quoteResponse, appDataInfo, orderToSign, tradeParameters: tradeParameters }, + result: { amountsAndCosts, quoteResponse, appDataInfo, orderToSign, tradeParameters, orderTypedData }, orderBookApi, } } diff --git a/src/trading/types.ts b/src/trading/types.ts index ebdd6831..143fe2ba 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -8,6 +8,29 @@ import type { UnsignedOrder } from '../order-signing' export type PrivateKey = string // 64 characters export type AccountAddress = `0x${string}` // 42 characters +export const ORDER_PRIMARY_TYPE = 'Order' as const + +interface TypedDataDomain { + name: string + version: string + chainId: number + verifyingContract: string +} + +interface TypedDataField { + name: string + type: string +} + +export interface OrderTypedData { + domain: TypedDataDomain + primaryType: typeof ORDER_PRIMARY_TYPE + types: { + Order: TypedDataField[] + } + message: UnsignedOrder +} + export interface TradeBaseParameters { kind: OrderKind sellToken: Address @@ -62,14 +85,11 @@ export interface QuoteResults { orderToSign: UnsignedOrder quoteResponse: OrderQuoteResponse appDataInfo: AppDataInfo + orderTypedData: OrderTypedData } -export interface QuoteResultsSerialized { - tradeParameters: TradeParameters +export interface QuoteResultsSerialized extends Omit { amountsAndCosts: QuoteAmountsAndCosts - orderToSign: UnsignedOrder - quoteResponse: OrderQuoteResponse - appDataInfo: AppDataInfo } export interface QuoteAndPost { From 228f3d716f30fbb6f8acbcf45212a2a94a765b67 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Fri, 22 Nov 2024 17:03:52 +0500 Subject: [PATCH 40/67] fix: fix order signing --- package.json | 2 +- src/trading/getOrderTypedData.ts | 8 ++++++++ src/trading/types.ts | 4 +--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 83b22600..3a63bb4a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "5.8.0-RC.4", + "version": "5.8.0-RC.5", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" diff --git a/src/trading/getOrderTypedData.ts b/src/trading/getOrderTypedData.ts index 3edc9f2f..327b9acf 100644 --- a/src/trading/getOrderTypedData.ts +++ b/src/trading/getOrderTypedData.ts @@ -3,6 +3,13 @@ import { ORDER_PRIMARY_TYPE, OrderTypedData } from './types' import { OrderSigningUtils, UnsignedOrder } from '../order-signing' import { SupportedChainId } from '../common' +const EIP712DomainTypes = [ + { name: 'name', type: 'string' }, + { name: 'version', type: 'string' }, + { name: 'chainId', type: 'uint256' }, + { name: 'verifyingContract', type: 'address' }, +] + export async function getOrderTypedData( chainId: SupportedChainId, orderToSign: UnsignedOrder @@ -14,6 +21,7 @@ export async function getOrderTypedData( primaryType: ORDER_PRIMARY_TYPE, types: { [ORDER_PRIMARY_TYPE]: ORDER_TYPE_FIELDS, + EIP712Domain: EIP712DomainTypes, }, message: orderToSign, } diff --git a/src/trading/types.ts b/src/trading/types.ts index 143fe2ba..92e2f42b 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -25,9 +25,7 @@ interface TypedDataField { export interface OrderTypedData { domain: TypedDataDomain primaryType: typeof ORDER_PRIMARY_TYPE - types: { - Order: TypedDataField[] - } + types: Record message: UnsignedOrder } From e1ac3b97939edbdb42b142312e9fa2778c0e0ea0 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 26 Nov 2024 16:05:31 +0500 Subject: [PATCH 41/67] fix: override sellToken with wrapped for eth-flow --- src/trading/getQuote.ts | 15 +++++++++++---- src/trading/postOnChainTrade.ts | 17 ++++++++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index b5bd08e5..f876e7a7 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -27,11 +27,20 @@ import { getOrderTypedData } from './getOrderTypedData' export type QuoteResultsWithSigner = { result: QuoteResults & { signer: Signer }; orderBookApi: OrderBookApi } export async function getQuote( - tradeParameters: TradeParameters, + _tradeParameters: TradeParameters, trader: QuoterParameters, advancedSettings?: SwapAdvancedSettings, _orderBookApi?: OrderBookApi ): Promise<{ result: QuoteResults; orderBookApi: OrderBookApi }> { + const { appCode, chainId, account: from } = trader + + const tradeParameters = getIsEthFlowOrder(_tradeParameters) + ? { + ..._tradeParameters, + sellToken: WRAPPED_NATIVE_CURRENCIES[chainId], + } + : _tradeParameters + const { sellToken, sellTokenDecimals, @@ -45,8 +54,6 @@ export async function getQuote( env = 'prod', } = tradeParameters - const { appCode, chainId, account: from } = trader - log(`Swap ${amount} ${sellToken} for ${buyToken} on chain ${chainId}`) const orderBookApi = _orderBookApi || new OrderBookApi({ chainId, env }) @@ -69,7 +76,7 @@ export async function getQuote( const quoteRequest: OrderQuoteRequest = { from, - sellToken: getIsEthFlowOrder(tradeParameters) ? WRAPPED_NATIVE_CURRENCIES[chainId] : sellToken, + sellToken, buyToken, receiver, validFor, diff --git a/src/trading/postOnChainTrade.ts b/src/trading/postOnChainTrade.ts index 12ab984b..3e0bf52f 100644 --- a/src/trading/postOnChainTrade.ts +++ b/src/trading/postOnChainTrade.ts @@ -3,7 +3,13 @@ import { AppDataInfo, LimitTradeParameters } from './types' import { calculateUniqueOrderId, EthFlowOrderExistsCallback } from './calculateUniqueOrderId' import { getOrderToSign } from './getOrderToSign' import { type EthFlow, EthFlow__factory } from '../common/generated' -import { BARN_ETH_FLOW_ADDRESSES, CowEnv, ETH_FLOW_ADDRESSES, SupportedChainId } from '../common' +import { + BARN_ETH_FLOW_ADDRESSES, + CowEnv, + ETH_FLOW_ADDRESSES, + SupportedChainId, + WRAPPED_NATIVE_CURRENCIES, +} from '../common' import { GAS_LIMIT_DEFAULT, log } from './consts' import type { EthFlowOrder } from '../common/generated/EthFlow' import { OrderBookApi } from '../order-book' @@ -12,14 +18,19 @@ export async function postOnChainTrade( orderBookApi: OrderBookApi, signer: Signer, appData: Pick, - params: LimitTradeParameters, + _params: LimitTradeParameters, networkCostsAmount = '0', checkEthFlowOrderExists?: EthFlowOrderExistsCallback ): Promise<{ txHash: string; orderId: string }> { + const chainId = orderBookApi.context.chainId + + const params = { + ..._params, + sellToken: WRAPPED_NATIVE_CURRENCIES[chainId], + } const { quoteId } = params const { appDataKeccak256, fullAppData } = appData - const chainId = await signer.getChainId() const from = await signer.getAddress() const contract = getEthFlowContract(chainId, signer, params.env) From dccbc421bb686e2963734f14876e8aadd31c14f1 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 26 Nov 2024 16:54:22 +0500 Subject: [PATCH 42/67] feat(trading): function to generate eth-flow transaction --- src/trading/getEthFlowTransaction.ts | 88 ++++++++++++++++++++++++++++ src/trading/getQuote.ts | 9 ++- src/trading/index.ts | 1 + src/trading/postOnChainTrade.test.ts | 28 +++++---- src/trading/postOnChainTrade.ts | 82 ++++---------------------- src/trading/types.ts | 7 +++ 6 files changed, 133 insertions(+), 82 deletions(-) create mode 100644 src/trading/getEthFlowTransaction.ts diff --git a/src/trading/getEthFlowTransaction.ts b/src/trading/getEthFlowTransaction.ts new file mode 100644 index 00000000..e871083d --- /dev/null +++ b/src/trading/getEthFlowTransaction.ts @@ -0,0 +1,88 @@ +import { Signer } from 'ethers' +import { LimitTradeParameters, TransactionParams } from './types' +import { calculateUniqueOrderId, EthFlowOrderExistsCallback } from './calculateUniqueOrderId' +import { getOrderToSign } from './getOrderToSign' +import { type EthFlow, EthFlow__factory } from '../common/generated' +import { + BARN_ETH_FLOW_ADDRESSES, + CowEnv, + ETH_FLOW_ADDRESSES, + SupportedChainId, + WRAPPED_NATIVE_CURRENCIES, +} from '../common' +import { GAS_LIMIT_DEFAULT } from './consts' +import type { EthFlowOrder } from '../common/generated/EthFlow' + +export async function getEthFlowTransaction( + signer: Signer, + appDataKeccak256: string, + _params: LimitTradeParameters, + networkCostsAmount = '0', + checkEthFlowOrderExists?: EthFlowOrderExistsCallback +): Promise<{ orderId: string; transaction: TransactionParams }> { + const chainId = (await signer.getChainId()) as SupportedChainId + const from = await signer.getAddress() + + const params = { + ..._params, + sellToken: WRAPPED_NATIVE_CURRENCIES[chainId], + } + const { quoteId } = params + + const contract = getEthFlowContract(chainId, signer, params.env) + const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appDataKeccak256) + const orderId = await calculateUniqueOrderId(chainId, orderToSign, checkEthFlowOrderExists, params.env) + + const ethOrderParams: EthFlowOrder.DataStruct = { + ...orderToSign, + quoteId, + appData: appDataKeccak256, + validTo: orderToSign.validTo.toString(), + } + + const estimatedGas = await contract.estimateGas + .createOrder(ethOrderParams, { value: orderToSign.sellAmount }) + .then((res) => BigInt(res.toHexString())) + .catch((error) => { + console.error(error) + + return GAS_LIMIT_DEFAULT + }) + + const callData = contract.interface.encodeFunctionData('createOrder', [ethOrderParams]) + + return { + orderId, + transaction: { + callData, + gasLimit: calculateGasMargin(estimatedGas).toString(), + to: contract.address, + value: orderToSign.sellAmount, + }, + } +} + +const ethFlowContractCache: Partial> = {} + +function getEthFlowContract(chainId: SupportedChainId, signer: Signer, env?: CowEnv): EthFlow { + const cache = ethFlowContractCache[chainId] + + if (cache) return cache + + const contract = EthFlow__factory.connect( + (env === 'staging' ? BARN_ETH_FLOW_ADDRESSES : ETH_FLOW_ADDRESSES)[chainId], + signer + ) + + ethFlowContractCache[chainId] = contract + + return contract +} + +/** + * Returns the gas value plus a margin for unexpected or variable gas costs (20%) + * @param value the gas value to pad + */ +function calculateGasMargin(value: bigint): bigint { + return value + (value * BigInt(20)) / BigInt(100) +} diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index f876e7a7..e21febd5 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -111,7 +111,14 @@ export async function getQuote( const orderTypedData = await getOrderTypedData(chainId, orderToSign) return { - result: { amountsAndCosts, quoteResponse, appDataInfo, orderToSign, tradeParameters, orderTypedData }, + result: { + amountsAndCosts, + quoteResponse, + appDataInfo, + orderToSign, + tradeParameters, + orderTypedData, + }, orderBookApi, } } diff --git a/src/trading/index.ts b/src/trading/index.ts index 7439dd7b..a2e20ed0 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -10,6 +10,7 @@ export { postLimitOrder } from './postLimitOrder' export { postCoWProtocolTrade } from './postCoWProtocolTrade' export { getOrderToSign } from './getOrderToSign' export { postOnChainTrade } from './postOnChainTrade' +export { getEthFlowTransaction } from './getEthFlowTransaction' /** * Helpers diff --git a/src/trading/postOnChainTrade.test.ts b/src/trading/postOnChainTrade.test.ts index b64e3170..4590d265 100644 --- a/src/trading/postOnChainTrade.test.ts +++ b/src/trading/postOnChainTrade.test.ts @@ -25,7 +25,7 @@ jest.mock('../common/generated', () => { import { VoidSigner } from '@ethersproject/abstract-signer' import { AppDataInfo, LimitOrderParameters } from './types' -import { SupportedChainId } from '../common' +import { SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' import { OrderBookApi, OrderKind } from '../order-book' import { postOnChainTrade } from './postOnChainTrade' @@ -33,7 +33,7 @@ const defaultOrderParams: LimitOrderParameters = { chainId: SupportedChainId.GNOSIS_CHAIN, signer: '1bb337bafb276f779c3035874b8914e4b851bb989dbb34e776397076576f3804', appCode: '0x007', - sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', sellTokenDecimals: 18, buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', buyTokenDecimals: 18, @@ -47,8 +47,12 @@ const defaultOrderParams: LimitOrderParameters = { const account = '0x21c3de23d98caddc406e3d31b25e807addf33333' const signer = new VoidSigner(account) + +const sendTransactionMock = jest.fn().mockResolvedValue({ txHash: '0xccdd11', orderId: '0xabc22' }) signer.getChainId = jest.fn().mockResolvedValue(SupportedChainId.GNOSIS_CHAIN) +signer.sendTransaction = sendTransactionMock +const callData = '0x123456' const currentTimestamp = 1487076708000 const uploadAppDataMock = jest.fn() @@ -65,6 +69,9 @@ const ethFlowContractMock = { createOrder: jest.fn(), }, createOrder: jest.fn(), + interface: { + encodeFunctionData: jest.fn().mockReturnValue(callData), + }, } describe('postOnChainTrade', () => { @@ -76,7 +83,6 @@ describe('postOnChainTrade', () => { ethFlowContractFactoryMock.mockReturnValue(ethFlowContractMock) uploadAppDataMock.mockResolvedValue(undefined) ethFlowContractMock.estimateGas.createOrder.mockResolvedValue({ toHexString: () => '0x1' }) - ethFlowContractMock.createOrder.mockResolvedValue({ hash: '0x000cc' }) Date.now = jest.fn(() => currentTimestamp) }) @@ -85,7 +91,8 @@ describe('postOnChainTrade', () => { uploadAppDataMock.mockReset() ethFlowContractFactoryMock.mockReset() ethFlowContractMock.estimateGas.createOrder.mockReset() - ethFlowContractMock.createOrder.mockReset() + ethFlowContractMock.interface.encodeFunctionData.mockReset() + sendTransactionMock.mockReset() }) it('Should call checkEthFlowOrderExists if it is set', async () => { @@ -107,19 +114,19 @@ describe('postOnChainTrade', () => { await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) - const call = ethFlowContractMock.createOrder.mock.calls[0][1] + const call = sendTransactionMock.mock.calls[0][0] - expect(call.gasLimit).toBe(BigInt(180000)) // 150000 by default + 20% + expect(call.gasLimit).toBe(BigInt(180000).toString()) // 150000 by default + 20% }) it('Should create an on-chain transaction with all specified parameters', async () => { await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) - expect(ethFlowContractMock.createOrder).toHaveBeenCalledTimes(1) - expect(ethFlowContractMock.createOrder).toHaveBeenCalledWith( + expect(ethFlowContractMock.interface.encodeFunctionData).toHaveBeenCalledTimes(1) + expect(ethFlowContractMock.interface.encodeFunctionData).toHaveBeenCalledWith('createOrder', [ { appData: appDataMock.appDataKeccak256, - sellToken: defaultOrderParams.sellToken, + sellToken: WRAPPED_NATIVE_CURRENCIES[defaultOrderParams.chainId], sellAmount: defaultOrderParams.sellAmount, sellTokenBalance: 'erc20', buyAmount: '1990000000000000000', // defaultOrderParams.buyAmount - slippage @@ -132,7 +139,6 @@ describe('postOnChainTrade', () => { receiver: account, validTo: defaultOrderParams.validTo!.toString(), }, - { value: defaultOrderParams.sellAmount, gasLimit: BigInt(1) } - ) + ]) }) }) diff --git a/src/trading/postOnChainTrade.ts b/src/trading/postOnChainTrade.ts index 3e0bf52f..fd9537ac 100644 --- a/src/trading/postOnChainTrade.ts +++ b/src/trading/postOnChainTrade.ts @@ -1,18 +1,10 @@ import { Signer } from 'ethers' import { AppDataInfo, LimitTradeParameters } from './types' -import { calculateUniqueOrderId, EthFlowOrderExistsCallback } from './calculateUniqueOrderId' -import { getOrderToSign } from './getOrderToSign' -import { type EthFlow, EthFlow__factory } from '../common/generated' -import { - BARN_ETH_FLOW_ADDRESSES, - CowEnv, - ETH_FLOW_ADDRESSES, - SupportedChainId, - WRAPPED_NATIVE_CURRENCIES, -} from '../common' -import { GAS_LIMIT_DEFAULT, log } from './consts' -import type { EthFlowOrder } from '../common/generated/EthFlow' +import { EthFlowOrderExistsCallback } from './calculateUniqueOrderId' + +import { log } from './consts' import { OrderBookApi } from '../order-book' +import { getEthFlowTransaction } from './getEthFlowTransaction' export async function postOnChainTrade( orderBookApi: OrderBookApi, @@ -22,72 +14,22 @@ export async function postOnChainTrade( networkCostsAmount = '0', checkEthFlowOrderExists?: EthFlowOrderExistsCallback ): Promise<{ txHash: string; orderId: string }> { - const chainId = orderBookApi.context.chainId - - const params = { - ..._params, - sellToken: WRAPPED_NATIVE_CURRENCIES[chainId], - } - const { quoteId } = params const { appDataKeccak256, fullAppData } = appData - const from = await signer.getAddress() - - const contract = getEthFlowContract(chainId, signer, params.env) - const orderToSign = getOrderToSign({ from, networkCostsAmount }, params, appDataKeccak256) - const orderId = await calculateUniqueOrderId(chainId, orderToSign, checkEthFlowOrderExists, params.env) - - const ethOrderParams: EthFlowOrder.DataStruct = { - ...orderToSign, - quoteId, - appData: appDataKeccak256, - validTo: orderToSign.validTo.toString(), - } + const { orderId, transaction } = await getEthFlowTransaction( + signer, + appDataKeccak256, + _params, + networkCostsAmount, + checkEthFlowOrderExists + ) log('Uploading app-data') await orderBookApi.uploadAppData(appDataKeccak256, fullAppData) - log('Estimating on-chain order gas') - const estimatedGas = await contract.estimateGas - .createOrder(ethOrderParams, { value: orderToSign.sellAmount }) - .then((res) => BigInt(res.toHexString())) - .catch((error) => { - console.error(error) - - return GAS_LIMIT_DEFAULT - }) - log('Sending on-chain order transaction') - const txReceipt = await contract.createOrder(ethOrderParams, { - value: orderToSign.sellAmount, - gasLimit: calculateGasMargin(estimatedGas), - }) + const txReceipt = await signer.sendTransaction(transaction) log(`On-chain order transaction sent, txHash: ${txReceipt.hash}, order: ${orderId}`) return { txHash: txReceipt.hash, orderId } } - -const ethFlowContractCache: Partial> = {} - -function getEthFlowContract(chainId: SupportedChainId, signer: Signer, env?: CowEnv): EthFlow { - const cache = ethFlowContractCache[chainId] - - if (cache) return cache - - const contract = EthFlow__factory.connect( - (env === 'staging' ? BARN_ETH_FLOW_ADDRESSES : ETH_FLOW_ADDRESSES)[chainId], - signer - ) - - ethFlowContractCache[chainId] = contract - - return contract -} - -/** - * Returns the gas value plus a margin for unexpected or variable gas costs (20%) - * @param value the gas value to pad - */ -function calculateGasMargin(value: bigint): bigint { - return value + (value * BigInt(20)) / BigInt(100) -} diff --git a/src/trading/types.ts b/src/trading/types.ts index 92e2f42b..2554b69e 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -111,3 +111,10 @@ export interface AppDataInfo { appDataKeccak256: string env?: CowEnv } + +export interface TransactionParams { + callData: string + gasLimit: string + to: string + value: string +} From 9bc094d3af02b7f8fa541b9eb782de91d3a3789e Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 26 Nov 2024 17:00:57 +0500 Subject: [PATCH 43/67] chore: export swapParamsToLimitOrderParams --- src/trading/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/trading/index.ts b/src/trading/index.ts index a2e20ed0..837d4d3c 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -18,3 +18,4 @@ export { getEthFlowTransaction } from './getEthFlowTransaction' export * from './appDataUtils' export * from './calculateUniqueOrderId' +export { swapParamsToLimitOrderParams } from './utils' From 3e550862d39d1572ffc6f4f461b010cb05d07fa7 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 26 Nov 2024 17:35:04 +0500 Subject: [PATCH 44/67] fix: use hex numbers in transaction --- src/trading/getEthFlowTransaction.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/trading/getEthFlowTransaction.ts b/src/trading/getEthFlowTransaction.ts index e871083d..7b674cdc 100644 --- a/src/trading/getEthFlowTransaction.ts +++ b/src/trading/getEthFlowTransaction.ts @@ -55,9 +55,9 @@ export async function getEthFlowTransaction( orderId, transaction: { callData, - gasLimit: calculateGasMargin(estimatedGas).toString(), + gasLimit: '0x' + calculateGasMargin(estimatedGas).toString(16), to: contract.address, - value: orderToSign.sellAmount, + value: '0x' + BigInt(orderToSign.sellAmount).toString(16), }, } } From 718b2123fbb74856c3ddcecadd9ed8bbcb12b833 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 26 Nov 2024 17:54:18 +0500 Subject: [PATCH 45/67] fix(trading): fix order amounts calculation --- src/trading/getQuote.ts | 3 ++- src/trading/postSwapOrder.ts | 5 +++-- src/trading/tradingSdk.ts | 4 +++- src/trading/utils.ts | 14 +++++++++----- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index e21febd5..c028eeb4 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -104,7 +104,8 @@ export async function getQuote( const orderToSign = getOrderToSign( { from, networkCostsAmount: quoteResponse.quote.feeAmount }, - swapParamsToLimitOrderParams(tradeParameters, quoteResponse), + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + swapParamsToLimitOrderParams(tradeParameters, quoteResponse.id!, amountsAndCosts), appDataInfo.appDataKeccak256 ) diff --git a/src/trading/postSwapOrder.ts b/src/trading/postSwapOrder.ts index 386e8e47..88902054 100644 --- a/src/trading/postSwapOrder.ts +++ b/src/trading/postSwapOrder.ts @@ -10,13 +10,14 @@ export async function postSwapOrder(params: SwapParameters, advancedSettings?: S export async function postSwapOrderFromQuote({ orderBookApi, - result: { signer, appDataInfo, quoteResponse, tradeParameters }, + result: { signer, appDataInfo, quoteResponse, tradeParameters, amountsAndCosts }, }: QuoteResultsWithSigner): Promise { return postCoWProtocolTrade( orderBookApi, signer, appDataInfo, - swapParamsToLimitOrderParams(tradeParameters, quoteResponse), + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + swapParamsToLimitOrderParams(tradeParameters, quoteResponse.id!, amountsAndCosts), quoteResponse.quote.feeAmount ) } diff --git a/src/trading/tradingSdk.ts b/src/trading/tradingSdk.ts index 874c93a9..e2d77453 100644 --- a/src/trading/tradingSdk.ts +++ b/src/trading/tradingSdk.ts @@ -26,11 +26,13 @@ export class TradingSdk { async postOnChainTrade(params: TradeParameters, advancedSettings?: SwapAdvancedSettings) { const quoteResults = await getQuoteWithSigner(this.mergeParams(params), advancedSettings) + const { tradeParameters, quoteResponse, amountsAndCosts } = quoteResults.result return postOnChainTrade( quoteResults.orderBookApi, quoteResults.result.signer, quoteResults.result.appDataInfo, - swapParamsToLimitOrderParams(quoteResults.result.tradeParameters, quoteResults.result.quoteResponse) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + swapParamsToLimitOrderParams(tradeParameters, quoteResponse.id!, amountsAndCosts) ) } diff --git a/src/trading/utils.ts b/src/trading/utils.ts index c31120f9..67965efb 100644 --- a/src/trading/utils.ts +++ b/src/trading/utils.ts @@ -1,16 +1,20 @@ import { AccountAddress, LimitTradeParameters, PrivateKey, TradeParameters } from './types' -import { OrderQuoteResponse } from '../order-book' +import { QuoteAmountsAndCosts } from '../order-book' import { ETH_ADDRESS } from '../common' import { ethers, Signer } from 'ethers' import { type ExternalProvider, Web3Provider } from '@ethersproject/providers' export function swapParamsToLimitOrderParams( params: TradeParameters, - { quote: { sellAmount, buyAmount }, id }: OrderQuoteResponse + quoteId: number, + amounts: QuoteAmountsAndCosts ): LimitTradeParameters { - // In this SDK we always use Optimal quotes which are always have id - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return { ...params, sellAmount, buyAmount, quoteId: id! } + return { + ...params, + sellAmount: amounts.afterSlippage.sellAmount.toString(), + buyAmount: amounts.afterSlippage.buyAmount.toString(), + quoteId, + } } export function getIsEthFlowOrder(params: { sellToken: string }): boolean { From 8e83b089c5ae5579a8af6a1ad1b255d9eb0bd473 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 26 Nov 2024 18:00:54 +0500 Subject: [PATCH 46/67] chore: bump rc --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a63bb4a..c787084a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "5.8.0-RC.5", + "version": "5.8.0-RC.6", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" From 54e279bd71c0fcdd80efefaa33db3a1e10ebb718 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 26 Nov 2024 18:14:04 +0500 Subject: [PATCH 47/67] chore: fix tests --- examples/vanilla/src/formState.ts | 17 +++++++++++++++-- src/trading/postOnChainTrade.test.ts | 10 +++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/examples/vanilla/src/formState.ts b/examples/vanilla/src/formState.ts index 9a669c28..4ee1f8b2 100644 --- a/examples/vanilla/src/formState.ts +++ b/examples/vanilla/src/formState.ts @@ -11,6 +11,20 @@ interface FormState { kind: 'sell' | 'buy' } +const DECIMALS_SHIFT = 6 + +/** + * This function converts input amount to the correct number of decimals. + * For example, if the input amount is 1.23 and the token has 18 decimals, + * the result will be 1230000000000000000. + * Since this is a simplified example, we only allow input amounts with maximum 6 decimals. + */ +const adjustDecimals = (amount: number, decimals: number) => { + const multiplicator = decimals > DECIMALS_SHIFT ? DECIMALS_SHIFT : 0 + + return BigInt(amount * 10 ** multiplicator) * BigInt(10 ** (decimals - multiplicator)) +} + export const getFormState = (): FormState => { return Object.fromEntries(new FormData(document.getElementById('form') as HTMLFormElement)) as unknown as FormState } @@ -30,8 +44,7 @@ export const getTradeParameters = (): TradeParameters => { const sellToken = TOKENS[chainId].find((t) => t.address === _sellToken) const buyToken = TOKENS[chainId].find((t) => t.address === _buyToken) const decimals = isSell ? sellToken.decimals : buyToken.decimals - const multiplicator = decimals > 3 ? 3 : 0 - const amount = BigInt(+_amount * 10 ** multiplicator) * BigInt(10 ** (decimals - multiplicator)) + const amount = adjustDecimals(+_amount, decimals) const slippageBps = _slippageBps ? +_slippageBps : undefined return { diff --git a/src/trading/postOnChainTrade.test.ts b/src/trading/postOnChainTrade.test.ts index 4590d265..09287d3b 100644 --- a/src/trading/postOnChainTrade.test.ts +++ b/src/trading/postOnChainTrade.test.ts @@ -48,9 +48,7 @@ const defaultOrderParams: LimitOrderParameters = { const account = '0x21c3de23d98caddc406e3d31b25e807addf33333' const signer = new VoidSigner(account) -const sendTransactionMock = jest.fn().mockResolvedValue({ txHash: '0xccdd11', orderId: '0xabc22' }) signer.getChainId = jest.fn().mockResolvedValue(SupportedChainId.GNOSIS_CHAIN) -signer.sendTransaction = sendTransactionMock const callData = '0x123456' const currentTimestamp = 1487076708000 @@ -83,6 +81,9 @@ describe('postOnChainTrade', () => { ethFlowContractFactoryMock.mockReturnValue(ethFlowContractMock) uploadAppDataMock.mockResolvedValue(undefined) ethFlowContractMock.estimateGas.createOrder.mockResolvedValue({ toHexString: () => '0x1' }) + signer.sendTransaction = jest.fn().mockImplementation(() => { + return Promise.resolve({ hash: '0xccdd11', orderId: '0xabc22' }) + }) Date.now = jest.fn(() => currentTimestamp) }) @@ -92,7 +93,6 @@ describe('postOnChainTrade', () => { ethFlowContractFactoryMock.mockReset() ethFlowContractMock.estimateGas.createOrder.mockReset() ethFlowContractMock.interface.encodeFunctionData.mockReset() - sendTransactionMock.mockReset() }) it('Should call checkEthFlowOrderExists if it is set', async () => { @@ -114,9 +114,9 @@ describe('postOnChainTrade', () => { await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) - const call = sendTransactionMock.mock.calls[0][0] + const call = (signer.sendTransaction as jest.Mock).mock.calls[0][0] - expect(call.gasLimit).toBe(BigInt(180000).toString()) // 150000 by default + 20% + expect(+call.gasLimit).toBe(180000) // 150000 by default + 20% }) it('Should create an on-chain transaction with all specified parameters', async () => { From 365a6042c848c5d6c6eb9cbd049e741456ae89fd Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 26 Nov 2024 18:36:17 +0500 Subject: [PATCH 48/67] chore: add mapQuoteAmountsAndCosts util --- package.json | 2 +- src/trading/index.ts | 2 +- src/trading/utils.ts | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c787084a..3c27ac2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "5.8.0-RC.6", + "version": "5.8.0-RC.7", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" diff --git a/src/trading/index.ts b/src/trading/index.ts index 837d4d3c..e316e43b 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -18,4 +18,4 @@ export { getEthFlowTransaction } from './getEthFlowTransaction' export * from './appDataUtils' export * from './calculateUniqueOrderId' -export { swapParamsToLimitOrderParams } from './utils' +export { swapParamsToLimitOrderParams, mapQuoteAmountsAndCosts } from './utils' diff --git a/src/trading/utils.ts b/src/trading/utils.ts index 67965efb..45303a91 100644 --- a/src/trading/utils.ts +++ b/src/trading/utils.ts @@ -36,3 +36,39 @@ export function getSigner(signer: Signer | ExternalProvider | PrivateKey): Signe export function isAccountAddress(address: any): address is AccountAddress { return typeof address === 'string' && /^0x[0-9a-fA-F]{40}$/.test(address) } + +export function mapQuoteAmountsAndCosts( + value: QuoteAmountsAndCosts, + mapper: (value: T) => R +): QuoteAmountsAndCosts { + const { + costs: { networkFee, partnerFee }, + } = value + + function serializeAmounts(value: { sellAmount: T; buyAmount: T }): { sellAmount: R; buyAmount: R } { + return { + sellAmount: mapper(value.sellAmount), + buyAmount: mapper(value.buyAmount), + } + } + + return { + ...value, + costs: { + ...value.costs, + networkFee: { + ...networkFee, + amountInSellCurrency: mapper(networkFee.amountInSellCurrency), + amountInBuyCurrency: mapper(networkFee.amountInBuyCurrency), + }, + partnerFee: { + ...partnerFee, + amount: mapper(partnerFee.amount), + }, + }, + beforeNetworkCosts: serializeAmounts(value.beforeNetworkCosts), + afterNetworkCosts: serializeAmounts(value.afterNetworkCosts), + afterPartnerFees: serializeAmounts(value.afterPartnerFees), + afterSlippage: serializeAmounts(value.afterSlippage), + } +} From 0843dcaaba8a02a67a6e3349c2e8fbf7a2efbb05 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Tue, 26 Nov 2024 18:38:40 +0500 Subject: [PATCH 49/67] chore: fix types --- src/composable/ConditionalOrder.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/composable/ConditionalOrder.ts b/src/composable/ConditionalOrder.ts index d502e469..b7e00b68 100644 --- a/src/composable/ConditionalOrder.ts +++ b/src/composable/ConditionalOrder.ts @@ -6,7 +6,6 @@ import { ConditionalOrderArguments, ConditionalOrderParams, ContextFactory, - IsNotValid, IsValidResult, OwnerContext, PollParams, @@ -96,7 +95,7 @@ export abstract class ConditionalOrder { assertIsValid(): void { const isValidResult = this.isValid() if (!isValidResult.isValid) { - throw new Error(`Invalid order: ${(isValidResult as IsNotValid).reason}`) + throw new Error(`Invalid order: ${isValidResult.reason}`) } } @@ -257,7 +256,7 @@ export abstract class ConditionalOrder { if (!isValid.isValid) { return { result: PollResultCode.DONT_TRY_AGAIN, - reason: `InvalidConditionalOrder. Reason: ${(isValid as IsNotValid).reason}`, + reason: `InvalidConditionalOrder. Reason: ${isValid.reason}`, } } From bb96203b2ee598b1ef809f6fae95d0cb2c492034 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 27 Nov 2024 13:41:03 +0500 Subject: [PATCH 50/67] chore: do not cache ethflow contract --- src/trading/getEthFlowTransaction.ts | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/trading/getEthFlowTransaction.ts b/src/trading/getEthFlowTransaction.ts index 7b674cdc..c5de5ae1 100644 --- a/src/trading/getEthFlowTransaction.ts +++ b/src/trading/getEthFlowTransaction.ts @@ -62,21 +62,8 @@ export async function getEthFlowTransaction( } } -const ethFlowContractCache: Partial> = {} - function getEthFlowContract(chainId: SupportedChainId, signer: Signer, env?: CowEnv): EthFlow { - const cache = ethFlowContractCache[chainId] - - if (cache) return cache - - const contract = EthFlow__factory.connect( - (env === 'staging' ? BARN_ETH_FLOW_ADDRESSES : ETH_FLOW_ADDRESSES)[chainId], - signer - ) - - ethFlowContractCache[chainId] = contract - - return contract + return EthFlow__factory.connect((env === 'staging' ? BARN_ETH_FLOW_ADDRESSES : ETH_FLOW_ADDRESSES)[chainId], signer) } /** From 6b718f6c8ddf09431b8714a38df13ae55b479a4f Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 27 Nov 2024 14:40:52 +0500 Subject: [PATCH 51/67] test: test getEthFlowTransaction --- src/trading/getEthFlowTransaction.test.ts | 80 +++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/trading/getEthFlowTransaction.test.ts diff --git a/src/trading/getEthFlowTransaction.test.ts b/src/trading/getEthFlowTransaction.test.ts new file mode 100644 index 00000000..ad0e20dd --- /dev/null +++ b/src/trading/getEthFlowTransaction.test.ts @@ -0,0 +1,80 @@ +const GAS = '0x1e848' // 125000 + +jest.mock('cross-fetch', () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fetchMock = require('jest-fetch-mock') + // Require the original module to not be mocked... + const originalFetch = jest.requireActual('cross-fetch') + return { + __esModule: true, + ...originalFetch, + default: fetchMock, + } +}) +jest.mock('../common/generated', () => { + const original = jest.requireActual('../common/generated') + + return { + ...original, + EthFlow__factory: { + connect: jest.fn().mockReturnValue({ + address: '0xaa1', + estimateGas: { + createOrder: jest.fn().mockResolvedValue({ toHexString: () => GAS }), + }, + interface: { + encodeFunctionData: jest.fn().mockReturnValue('0x0ac'), + }, + }), + }, + } +}) + +import { getEthFlowTransaction } from './getEthFlowTransaction' +import { VoidSigner } from '@ethersproject/abstract-signer' +import { SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' +import { LimitTradeParameters } from './types' +import { OrderKind } from '../order-book' + +const appDataKeccak256 = '0x578c975b1cfd3e24c21fb599076c4f7879c4268efd33eed3eb9efa5e30efac21' + +const params: LimitTradeParameters = { + kind: OrderKind.SELL, + sellToken: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + buyToken: '0xdef1ca1fb7fbcdc777520aa7f396b4e015f497ab', + sellAmount: '12000000000000000', + buyAmount: '36520032402342342322', + quoteId: 3, + sellTokenDecimals: 18, + buyTokenDecimals: 18, +} + +describe('getEthFlowTransaction', () => { + const chainId = SupportedChainId.GNOSIS_CHAIN + const account = '0x21c3de23d98caddc406e3d31b25e807addf33333' + const signer = new VoidSigner(account) + + signer.getChainId = jest.fn().mockResolvedValue(chainId) + signer.getAddress = jest.fn().mockResolvedValue(account) + + it('Should always override sell token with wrapped native token', async () => { + const result = await getEthFlowTransaction(signer, appDataKeccak256, params) + const wrappedToken = WRAPPED_NATIVE_CURRENCIES[chainId] + + expect(result.transaction.callData.includes(params.sellToken.slice(2))).toBe(false) + expect(result.transaction.callData.includes(wrappedToken.slice(2))).toBe(false) + }) + + it('Should call gas estimation and return estimated value + 20%', async () => { + const result = await getEthFlowTransaction(signer, appDataKeccak256, params) + const gasNum = +GAS + + expect(+result.transaction.gasLimit).toBe(gasNum + gasNum * 0.2) + }) + + it('Transaction value should be equal to sell amount', async () => { + const result = await getEthFlowTransaction(signer, appDataKeccak256, params) + + expect(result.transaction.value).toBe('0x' + BigInt(params.sellAmount).toString(16)) + }) +}) From 6adfc55657b2cacfbf16354a725b2f92a7e68441 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 27 Nov 2024 16:52:36 +0500 Subject: [PATCH 52/67] feat(trading): add getPreSignTransaction function --- abi/GPv2Settlement.json | 89 +++++++++++++++++++++++ package.json | 2 +- src/order-signing/orderSigningUtils.ts | 2 +- src/trading/getEthFlowTransaction.ts | 9 +-- src/trading/getPreSignTransaction.test.ts | 60 +++++++++++++++ src/trading/getPreSignTransaction.ts | 35 +++++++++ src/trading/index.ts | 1 + src/trading/postOnChainTrade.test.ts | 2 +- src/trading/utils.ts | 10 ++- 9 files changed, 198 insertions(+), 12 deletions(-) create mode 100644 abi/GPv2Settlement.json create mode 100644 src/trading/getPreSignTransaction.test.ts create mode 100644 src/trading/getPreSignTransaction.ts diff --git a/abi/GPv2Settlement.json b/abi/GPv2Settlement.json new file mode 100644 index 00000000..da5a9a26 --- /dev/null +++ b/abi/GPv2Settlement.json @@ -0,0 +1,89 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "sellToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "buyToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sellAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "buyAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "orderUid", + "type": "bytes" + } + ], + "name": "Trade", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "orderUid", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "signed", + "type": "bool" + } + ], + "name": "setPreSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "orderUid", + "type": "bytes" + } + ], + "name": "invalidateOrder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "domainSeparator", + "outputs": [{ "name": "", "type": "bytes32" }], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/package.json b/package.json index 3c27ac2b..8102bfb6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "5.8.0-RC.7", + "version": "5.8.0-RC.8", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" diff --git a/src/order-signing/orderSigningUtils.ts b/src/order-signing/orderSigningUtils.ts index 4dbd5879..72f605dc 100644 --- a/src/order-signing/orderSigningUtils.ts +++ b/src/order-signing/orderSigningUtils.ts @@ -131,7 +131,7 @@ export class OrderSigningUtils { * signing orders using smart contracts, whereby this SDK cannot do the EIP-1271 signing for you. * @returns The EIP-712 types used for signing. */ - static getEIP712Types(): Record { + static getEIP712Types(): Record { return { Order: [ { name: 'sellToken', type: 'address' }, diff --git a/src/trading/getEthFlowTransaction.ts b/src/trading/getEthFlowTransaction.ts index c5de5ae1..4d2f63d1 100644 --- a/src/trading/getEthFlowTransaction.ts +++ b/src/trading/getEthFlowTransaction.ts @@ -12,6 +12,7 @@ import { } from '../common' import { GAS_LIMIT_DEFAULT } from './consts' import type { EthFlowOrder } from '../common/generated/EthFlow' +import { calculateGasMargin } from './utils' export async function getEthFlowTransaction( signer: Signer, @@ -65,11 +66,3 @@ export async function getEthFlowTransaction( function getEthFlowContract(chainId: SupportedChainId, signer: Signer, env?: CowEnv): EthFlow { return EthFlow__factory.connect((env === 'staging' ? BARN_ETH_FLOW_ADDRESSES : ETH_FLOW_ADDRESSES)[chainId], signer) } - -/** - * Returns the gas value plus a margin for unexpected or variable gas costs (20%) - * @param value the gas value to pad - */ -function calculateGasMargin(value: bigint): bigint { - return value + (value * BigInt(20)) / BigInt(100) -} diff --git a/src/trading/getPreSignTransaction.test.ts b/src/trading/getPreSignTransaction.test.ts new file mode 100644 index 00000000..439cff47 --- /dev/null +++ b/src/trading/getPreSignTransaction.test.ts @@ -0,0 +1,60 @@ +const GAS = '0x1e848' // 125000 + +jest.mock('cross-fetch', () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fetchMock = require('jest-fetch-mock') + // Require the original module to not be mocked... + const originalFetch = jest.requireActual('cross-fetch') + return { + __esModule: true, + ...originalFetch, + default: fetchMock, + } +}) +jest.mock('../common/generated', () => { + const original = jest.requireActual('../common/generated') + + return { + ...original, + GPv2Settlement__factory: { + connect: jest.fn().mockReturnValue({ + address: '0xaa1', + estimateGas: { + setPreSignature: jest.fn().mockResolvedValue({ toHexString: () => GAS }), + }, + interface: { + encodeFunctionData: jest.fn().mockReturnValue('0x0ac'), + }, + }), + }, + } +}) + +import { SupportedChainId } from '../common' +import { VoidSigner } from '@ethersproject/abstract-signer' +import { getPreSignTransaction } from './getPreSignTransaction' + +const chainId = SupportedChainId.GNOSIS_CHAIN +const account = '0x21c3de23d98caddc406e3d31b25e807addf33333' +const orderId = + '0xd64389693b6cf89ad6c140a113b10df08073e5ef3063d05a02f3f42e1a42f0ad0b7795e18767259cc253a2af471dbc4c72b49516ffffffff' + +describe('getPreSignTransaction', () => { + const signer = new VoidSigner(account) + + signer.getChainId = jest.fn().mockResolvedValue(chainId) + signer.getAddress = jest.fn().mockResolvedValue(account) + + it('Should call gas estimation and return estimated value + 20%', async () => { + const result = await getPreSignTransaction(signer, chainId, account, orderId) + const gasNum = +GAS + + expect(+result.gasLimit).toBe(gasNum + gasNum * 0.2) + }) + + it('Tx value should always be zero', async () => { + const result = await getPreSignTransaction(signer, chainId, account, orderId) + + expect(result.value).toBe('0') + }) +}) diff --git a/src/trading/getPreSignTransaction.ts b/src/trading/getPreSignTransaction.ts new file mode 100644 index 00000000..ba1db1eb --- /dev/null +++ b/src/trading/getPreSignTransaction.ts @@ -0,0 +1,35 @@ +import { COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS, SupportedChainId } from '../common' +import type { Signer } from 'ethers' +import { GAS_LIMIT_DEFAULT } from './consts' +import { calculateGasMargin } from './utils' + +import { GPv2Settlement__factory } from '../common/generated' +import { TransactionParams } from './types' + +export async function getPreSignTransaction( + signer: Signer, + chainId: SupportedChainId, + account: string, + orderId: string +): Promise { + const contract = GPv2Settlement__factory.connect(account, signer) + + const settlementContractAddress = COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS[chainId] as `0x${string}` + const preSignatureCall = contract.interface.encodeFunctionData('setPreSignature', [orderId, true]) + + const gas = await contract.estimateGas + .setPreSignature(orderId, true) + .then((res) => BigInt(res.toHexString())) + .catch((error) => { + console.error(error) + + return GAS_LIMIT_DEFAULT + }) + + return { + callData: preSignatureCall, + gasLimit: '0x' + calculateGasMargin(gas).toString(16), + to: settlementContractAddress, + value: '0', + } +} diff --git a/src/trading/index.ts b/src/trading/index.ts index e316e43b..da6b16c8 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -11,6 +11,7 @@ export { postCoWProtocolTrade } from './postCoWProtocolTrade' export { getOrderToSign } from './getOrderToSign' export { postOnChainTrade } from './postOnChainTrade' export { getEthFlowTransaction } from './getEthFlowTransaction' +export { getPreSignTransaction } from './getPreSignTransaction' /** * Helpers diff --git a/src/trading/postOnChainTrade.test.ts b/src/trading/postOnChainTrade.test.ts index 09287d3b..7f426535 100644 --- a/src/trading/postOnChainTrade.test.ts +++ b/src/trading/postOnChainTrade.test.ts @@ -137,7 +137,7 @@ describe('postOnChainTrade', () => { kind: defaultOrderParams.kind, quoteId: defaultOrderParams.quoteId, receiver: account, - validTo: defaultOrderParams.validTo!.toString(), + validTo: defaultOrderParams.validTo?.toString(), }, ]) }) diff --git a/src/trading/utils.ts b/src/trading/utils.ts index 45303a91..a996e4bc 100644 --- a/src/trading/utils.ts +++ b/src/trading/utils.ts @@ -33,10 +33,18 @@ export function getSigner(signer: Signer | ExternalProvider | PrivateKey): Signe return signer as Signer } -export function isAccountAddress(address: any): address is AccountAddress { +export function isAccountAddress(address: unknown): address is AccountAddress { return typeof address === 'string' && /^0x[0-9a-fA-F]{40}$/.test(address) } +/** + * Returns the gas value plus a margin for unexpected or variable gas costs (20%) + * @param value the gas value to pad + */ +export function calculateGasMargin(value: bigint): bigint { + return value + (value * BigInt(20)) / BigInt(100) +} + export function mapQuoteAmountsAndCosts( value: QuoteAmountsAndCosts, mapper: (value: T) => R From 1cf851f96bc9074c7f6209ed4f2e7d5fa5825a58 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 27 Nov 2024 18:00:44 +0500 Subject: [PATCH 53/67] chore: add more description to trading types --- src/trading/getEthFlowTransaction.ts | 6 +- src/trading/getPreSignTransaction.ts | 4 +- src/trading/types.ts | 85 +++++++++++++++++++++------- 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/trading/getEthFlowTransaction.ts b/src/trading/getEthFlowTransaction.ts index 4d2f63d1..ff099d55 100644 --- a/src/trading/getEthFlowTransaction.ts +++ b/src/trading/getEthFlowTransaction.ts @@ -50,13 +50,13 @@ export async function getEthFlowTransaction( return GAS_LIMIT_DEFAULT }) - const callData = contract.interface.encodeFunctionData('createOrder', [ethOrderParams]) + const data = contract.interface.encodeFunctionData('createOrder', [ethOrderParams]) return { orderId, transaction: { - callData, - gasLimit: '0x' + calculateGasMargin(estimatedGas).toString(16), + data, + gas: '0x' + calculateGasMargin(estimatedGas).toString(16), to: contract.address, value: '0x' + BigInt(orderToSign.sellAmount).toString(16), }, diff --git a/src/trading/getPreSignTransaction.ts b/src/trading/getPreSignTransaction.ts index ba1db1eb..86ff2fac 100644 --- a/src/trading/getPreSignTransaction.ts +++ b/src/trading/getPreSignTransaction.ts @@ -27,8 +27,8 @@ export async function getPreSignTransaction( }) return { - callData: preSignatureCall, - gasLimit: '0x' + calculateGasMargin(gas).toString(16), + data: preSignatureCall, + gas: '0x' + calculateGasMargin(gas).toString(16), to: settlementContractAddress, value: '0', } diff --git a/src/trading/types.ts b/src/trading/types.ts index 2554b69e..e0e56fde 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -1,5 +1,14 @@ import type { AppDataParams, latest, LatestAppDataDocVersion } from '@cowprotocol/app-data' -import type { Address, OrderKind, OrderQuoteRequest, OrderQuoteResponse, QuoteAmountsAndCosts } from '../order-book' +import { + AppData, + AppDataHash, + OrderKind, + OrderParameters, + OrderQuoteRequest, + OrderQuoteResponse, + QuoteAmountsAndCosts, + TokenAmount, +} from '../order-book' import type { Signer } from '@ethersproject/abstract-signer' import type { CowEnv, SupportedChainId } from '../common' import type { ExternalProvider } from '@ethersproject/providers' @@ -10,6 +19,9 @@ export type AccountAddress = `0x${string}` // 42 characters export const ORDER_PRIMARY_TYPE = 'Order' as const +/** + * EIP-712 typed data domain. + */ interface TypedDataDomain { name: string version: string @@ -17,11 +29,17 @@ interface TypedDataDomain { verifyingContract: string } +/** + * EIP-712 typed data field. + */ interface TypedDataField { name: string type: string } +/** + * EIP-712 typed data for an order. + */ export interface OrderTypedData { domain: TypedDataDomain primaryType: typeof ORDER_PRIMARY_TYPE @@ -29,41 +47,56 @@ export interface OrderTypedData { message: UnsignedOrder } +/** + * Minimal set of parameters to create a trade. + */ export interface TradeBaseParameters { kind: OrderKind - sellToken: Address + sellToken: OrderParameters['sellToken'] sellTokenDecimals: number - buyToken: Address + buyToken: OrderParameters['buyToken'] buyTokenDecimals: number - amount: string + amount: TokenAmount } +/** + * Optional parameters to create a trade. + */ export interface TradeOptionalParameters { env?: CowEnv - partiallyFillable?: boolean - slippageBps?: number - receiver?: string - validFor?: number + partiallyFillable?: OrderParameters['partiallyFillable'] + slippageBps?: latest.SlippageBips + receiver?: OrderParameters['receiver'] + validFor?: OrderParameters['validTo'] partnerFee?: latest.PartnerFee } +/** + * Information about the trader. + */ export interface TraderParameters { chainId: SupportedChainId - appCode: string + appCode: latest.AppCode signer: Signer | ExternalProvider | PrivateKey } export type QuoterParameters = Omit & { account: AccountAddress } +/** + * Trade type, assets, amounts, and optional parameters. + */ export interface TradeParameters extends TradeBaseParameters, TradeOptionalParameters {} export interface SwapParameters extends TradeParameters, TraderParameters {} export interface LimitTradeParameters extends Omit { - sellAmount: string - buyAmount: string + sellAmount: OrderParameters['sellAmount'] + buyAmount: OrderParameters['buyAmount'] + /** + * Id of the quote to be used for the limit order. + */ quoteId: number - validTo?: number + validTo?: OrderParameters['validTo'] } export interface LimitOrderParameters extends TraderParameters, LimitTradeParameters {} @@ -77,6 +110,10 @@ export interface LimitOrderAdvancedSettings { appData?: AppDataParams } +/** + * Exhaustive set of data which includes information about trade, quote, order, "app-data", and more. + * This data is used to create a trade, sign an order, and post it to the order book. + */ export interface QuoteResults { tradeParameters: TradeParameters amountsAndCosts: QuoteAmountsAndCosts @@ -92,29 +129,33 @@ export interface QuoteResultsSerialized extends Omit } -export type AppDataOrderClass = latest.OrderClass['orderClass'] - export type AppDataRootSchema = latest.AppDataRootSchema export interface BuildAppDataParams { - appCode: string - slippageBps: number - orderClass: AppDataOrderClass + appCode: latest.AppCode + slippageBps: latest.SlippageBips + orderClass: latest.OrderClass['orderClass'] } +/** + * https://github.com/cowprotocol/app-data + */ export interface AppDataInfo { doc: LatestAppDataDocVersion - fullAppData: string - appDataKeccak256: string - env?: CowEnv + fullAppData: AppData + appDataKeccak256: AppDataHash } +/** + * A standard Ethereum transaction object + */ export interface TransactionParams { - callData: string - gasLimit: string + data: string + gas: string to: string value: string } From 1ff1f2fb7d4cb0450d43db3968848277d772e441 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 27 Nov 2024 18:04:54 +0500 Subject: [PATCH 54/67] chore: fix test --- src/trading/getEthFlowTransaction.test.ts | 6 +++--- src/trading/getPreSignTransaction.test.ts | 2 +- src/trading/postOnChainTrade.test.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/trading/getEthFlowTransaction.test.ts b/src/trading/getEthFlowTransaction.test.ts index ad0e20dd..a15ea909 100644 --- a/src/trading/getEthFlowTransaction.test.ts +++ b/src/trading/getEthFlowTransaction.test.ts @@ -61,15 +61,15 @@ describe('getEthFlowTransaction', () => { const result = await getEthFlowTransaction(signer, appDataKeccak256, params) const wrappedToken = WRAPPED_NATIVE_CURRENCIES[chainId] - expect(result.transaction.callData.includes(params.sellToken.slice(2))).toBe(false) - expect(result.transaction.callData.includes(wrappedToken.slice(2))).toBe(false) + expect(result.transaction.data.includes(params.sellToken.slice(2))).toBe(false) + expect(result.transaction.data.includes(wrappedToken.slice(2))).toBe(false) }) it('Should call gas estimation and return estimated value + 20%', async () => { const result = await getEthFlowTransaction(signer, appDataKeccak256, params) const gasNum = +GAS - expect(+result.transaction.gasLimit).toBe(gasNum + gasNum * 0.2) + expect(+result.transaction.gas).toBe(gasNum + gasNum * 0.2) }) it('Transaction value should be equal to sell amount', async () => { diff --git a/src/trading/getPreSignTransaction.test.ts b/src/trading/getPreSignTransaction.test.ts index 439cff47..84cb496c 100644 --- a/src/trading/getPreSignTransaction.test.ts +++ b/src/trading/getPreSignTransaction.test.ts @@ -49,7 +49,7 @@ describe('getPreSignTransaction', () => { const result = await getPreSignTransaction(signer, chainId, account, orderId) const gasNum = +GAS - expect(+result.gasLimit).toBe(gasNum + gasNum * 0.2) + expect(+result.gas).toBe(gasNum + gasNum * 0.2) }) it('Tx value should always be zero', async () => { diff --git a/src/trading/postOnChainTrade.test.ts b/src/trading/postOnChainTrade.test.ts index 7f426535..e9296182 100644 --- a/src/trading/postOnChainTrade.test.ts +++ b/src/trading/postOnChainTrade.test.ts @@ -116,7 +116,7 @@ describe('postOnChainTrade', () => { const call = (signer.sendTransaction as jest.Mock).mock.calls[0][0] - expect(+call.gasLimit).toBe(180000) // 150000 by default + 20% + expect(+call.gas).toBe(180000) // 150000 by default + 20% }) it('Should create an on-chain transaction with all specified parameters', async () => { From b8fccffc0e83128252575eca490dec886ff7b336 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 28 Nov 2024 14:36:34 +0500 Subject: [PATCH 55/67] chore: update trading sdk readme --- src/order-signing/orderSigningUtils.ts | 8 ++++---- src/trading/README.md | 9 ++++----- src/trading/getQuote.ts | 4 ++-- src/trading/tradingSdk.ts | 9 ++++++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/order-signing/orderSigningUtils.ts b/src/order-signing/orderSigningUtils.ts index 72f605dc..025411c6 100644 --- a/src/order-signing/orderSigningUtils.ts +++ b/src/order-signing/orderSigningUtils.ts @@ -14,7 +14,7 @@ const ethersUtils = () => import('ethers/lib/utils') * @example * * ```typescript - * import { OrderSigningUtils, SupportedChainId } from '@cowprotocol/cow-sdk' + * import { OrderSigningUtils, SupportedChainId, UnsignedOrder } from '@cowprotocol/cow-sdk' * import { Web3Provider } from '@ethersproject/providers' * * const account = 'YOUR_WALLET_ADDRESS' @@ -23,10 +23,10 @@ const ethersUtils = () => import('ethers/lib/utils') * const signer = provider.getSigner() * * async function main() { - * const { order: Order } = { ... } - * const orderSigningResult = await OrderSigningUtils.signOrder(quote, chainId, signer) + * const orderToSign: UnsignedOrder = { ... } + * const orderSigningResult = await OrderSigningUtils.signOrder(orderToSign, chainId, signer) * - * const orderId = await orderBookApi.sendOrder({ ...quote, ...orderSigningResult }) + * const orderId = await orderBookApi.sendOrder({ ...orderToSign, ...orderSigningResult }) * * const order = await orderBookApi.getOrder(orderId) * diff --git a/src/trading/README.md b/src/trading/README.md index b3d4167a..68fee06a 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -93,14 +93,13 @@ In case if you want to get a quote and only then create an order, you can use th The parameters required are the same as for the `postSwapOrder` function. -The function returns a quote object with the following fields: - - `swapParameters` - the parameters used to get the quote +The function returns `quoteResults` object with the following properties: + - `tradeParameters` - trade type, assets, amounts and other optional parameters - `amountsAndCosts` - the order sell/buy amounts including network costs, fees and slippage - - `orderToSign` - the order to sign + - `orderToSign` - order parameters to sign (see [order signing](https://docs.cow.fi/cow-protocol/reference/sdks/cow-sdk/classes/OrderSigningUtils)) - `quoteResponse` - DTO from [quote API](https://api.cow.fi/docs/#/default/post_api_v1_quote) - `appDataInfo` - [order's metadata](https://docs.cow.fi/cow-protocol/reference/sdks/app-data) - - `orderBookApi` - instance of [`OrderBookApi`](../order-book/api.ts) - - `signer` - instance if Ethers signer + - `orderTypedData` - EIP-712 typed data for signing Another parameter is returned by this function is `postSwapOrderFromQuote`. It can be used to create an order from the received quote. diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index c028eeb4..d7daa756 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -113,11 +113,11 @@ export async function getQuote( return { result: { + tradeParameters, amountsAndCosts, + orderToSign, quoteResponse, appDataInfo, - orderToSign, - tradeParameters, orderTypedData, }, orderBookApi, diff --git a/src/trading/tradingSdk.ts b/src/trading/tradingSdk.ts index e2d77453..3bc4df92 100644 --- a/src/trading/tradingSdk.ts +++ b/src/trading/tradingSdk.ts @@ -15,15 +15,18 @@ import { swapParamsToLimitOrderParams } from './utils' export class TradingSdk { constructor(public readonly traderParams: TraderParameters) {} - async postSwapOrder(params: TradeParameters, advancedSettings?: SwapAdvancedSettings) { + async postSwapOrder(params: TradeParameters, advancedSettings?: SwapAdvancedSettings): Promise { return postSwapOrder(this.mergeParams(params), advancedSettings) } - async postLimitOrder(params: LimitTradeParameters, advancedSettings?: LimitOrderAdvancedSettings) { + async postLimitOrder(params: LimitTradeParameters, advancedSettings?: LimitOrderAdvancedSettings): Promise { return postLimitOrder(this.mergeParams(params), advancedSettings) } - async postOnChainTrade(params: TradeParameters, advancedSettings?: SwapAdvancedSettings) { + async postOnChainTrade( + params: TradeParameters, + advancedSettings?: SwapAdvancedSettings + ): Promise> { const quoteResults = await getQuoteWithSigner(this.mergeParams(params), advancedSettings) const { tradeParameters, quoteResponse, amountsAndCosts } = quoteResults.result From 2500eef43438280752ffa02b6b37c941ce89e144 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 28 Nov 2024 17:32:29 +0500 Subject: [PATCH 56/67] chore: up rc --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8102bfb6..94470ece 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "5.8.0-RC.8", + "version": "5.8.0-RC.9", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" From b26cf2ddabd25748048da9536c9cb21c8d5748dc Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 5 Dec 2024 13:24:20 +0500 Subject: [PATCH 57/67] chore: fix base contract addresses --- src/common/consts.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/consts.ts b/src/common/consts.ts index 1faaee91..7b811cf0 100644 --- a/src/common/consts.ts +++ b/src/common/consts.ts @@ -72,7 +72,7 @@ export const ETH_FLOW_ADDRESSES: Record = { [SupportedChainId.GNOSIS_CHAIN]: '0x40A50cf069e992AA4536211B23F286eF88752187', [SupportedChainId.ARBITRUM_ONE]: '0x552fcecc218158fff20e505c8f3ad24f8e1dd33c', [SupportedChainId.SEPOLIA]: '0x0b7795E18767259CC253a2dF471db34c72B49516', - [SupportedChainId.BASE]: '0x40A50cf069e992AA4536211B23F286eF88752187', + [SupportedChainId.BASE]: '0x3d1b389f1707DB3d4c5344d5669DBda6b5D6Ab51', } export const BARN_ETH_FLOW_ADDRESSES: Record = { @@ -80,7 +80,7 @@ export const BARN_ETH_FLOW_ADDRESSES: Record = { [SupportedChainId.GNOSIS_CHAIN]: '0xD02De8Da0B71E1B59489794F423FaBBa2AdC4d93', [SupportedChainId.ARBITRUM_ONE]: '0x6dfe75b5ddce1ade279d4fa6bd6aef3cbb6f49db', [SupportedChainId.SEPOLIA]: '0x2671994c7D224ac4799ac2cf6Ef9EF187d42C69f', - [SupportedChainId.BASE]: '0xD02De8Da0B71E1B59489794F423FaBBa2AdC4d93', + [SupportedChainId.BASE]: '0x3C3eA1829891BC9bEC3d06A81d5d169e52a415e3', } export const MAX_VALID_TO_EPOCH = 4294967295 // Max uint32 (Feb 07 2106 07:28:15 GMT+0100) From 26d822b72a1c15343250e0e376d816d7fd8f6a70 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 5 Dec 2024 13:30:19 +0500 Subject: [PATCH 58/67] fix: make quoteId optional for limit orders --- src/order-signing/utils.ts | 2 +- src/trading/README.md | 6 +++++- src/trading/getEthFlowTransaction.ts | 4 ++-- src/trading/postCoWProtocolTrade.ts | 16 ++++++++++++++-- src/trading/postOnChainTrade.ts | 4 ++-- src/trading/types.ts | 6 +++++- src/trading/utils.ts | 8 ++------ 7 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/order-signing/utils.ts b/src/order-signing/utils.ts index 0cb980c3..f3f2c2eb 100644 --- a/src/order-signing/utils.ts +++ b/src/order-signing/utils.ts @@ -247,12 +247,12 @@ export async function generateOrderId( params: Pick ): Promise<{ orderId: string; orderDigest: string }> { const domain = await getDomain(chainId) - // Different validTo when signing because EthFlow contract expects it to be max for all orders const orderDigest = hashOrder(domain, order) // Generate the orderId from owner, orderDigest, and max validTo const orderId = packOrderUidParams({ ...params, orderDigest, + // Different validTo when signing because EthFlow contract expects it to be max for all orders validTo: order.validTo, }) diff --git a/src/trading/README.md b/src/trading/README.md index 68fee06a..1ba42922 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -142,7 +142,7 @@ if (confirm(`You will get at least: ${buyAmount}, ok?`)) { ### postLimitOrder -This function is simpler than the `postSwapOrder` function, because it doesn't require a quote. +This main difference between this function and `postSwapOrder` is that here you need to specify both sell and buy amounts. You need to provide the following parameters: - `kind` - the order kind (sell/buy) @@ -153,6 +153,10 @@ You need to provide the following parameters: - `sellAmount` - the amount to sell in atoms - `buyAmount` - the amount to buy in atoms +And optional parameters: + - `quoteId` - id of the quote from the quote API (see getQuote function) + - `validTo` - the order expiration time in seconds + ```typescript import { SupportedChainId, diff --git a/src/trading/getEthFlowTransaction.ts b/src/trading/getEthFlowTransaction.ts index ff099d55..dd62a68f 100644 --- a/src/trading/getEthFlowTransaction.ts +++ b/src/trading/getEthFlowTransaction.ts @@ -1,5 +1,5 @@ import { Signer } from 'ethers' -import { LimitTradeParameters, TransactionParams } from './types' +import { LimitTradeParametersFromQuote, TransactionParams } from './types' import { calculateUniqueOrderId, EthFlowOrderExistsCallback } from './calculateUniqueOrderId' import { getOrderToSign } from './getOrderToSign' import { type EthFlow, EthFlow__factory } from '../common/generated' @@ -17,7 +17,7 @@ import { calculateGasMargin } from './utils' export async function getEthFlowTransaction( signer: Signer, appDataKeccak256: string, - _params: LimitTradeParameters, + _params: LimitTradeParametersFromQuote, networkCostsAmount = '0', checkEthFlowOrderExists?: EthFlowOrderExistsCallback ): Promise<{ orderId: string; transaction: TransactionParams }> { diff --git a/src/trading/postCoWProtocolTrade.ts b/src/trading/postCoWProtocolTrade.ts index 06faad4f..4985a0f4 100644 --- a/src/trading/postCoWProtocolTrade.ts +++ b/src/trading/postCoWProtocolTrade.ts @@ -15,9 +15,21 @@ export async function postCoWProtocolTrade( networkCostsAmount = '0' ): Promise { if (getIsEthFlowOrder(params)) { - const { orderId } = await postOnChainTrade(orderBookApi, signer, appData, params, networkCostsAmount) + const quoteId = params.quoteId - return orderId + if (typeof quoteId === 'number') { + const { orderId } = await postOnChainTrade( + orderBookApi, + signer, + appData, + { ...params, quoteId }, + networkCostsAmount + ) + + return orderId + } else { + throw new Error('quoteId is required for EthFlow orders') + } } const { quoteId = null } = params diff --git a/src/trading/postOnChainTrade.ts b/src/trading/postOnChainTrade.ts index fd9537ac..8c186216 100644 --- a/src/trading/postOnChainTrade.ts +++ b/src/trading/postOnChainTrade.ts @@ -1,5 +1,5 @@ import { Signer } from 'ethers' -import { AppDataInfo, LimitTradeParameters } from './types' +import { AppDataInfo, LimitTradeParametersFromQuote } from './types' import { EthFlowOrderExistsCallback } from './calculateUniqueOrderId' import { log } from './consts' @@ -10,7 +10,7 @@ export async function postOnChainTrade( orderBookApi: OrderBookApi, signer: Signer, appData: Pick, - _params: LimitTradeParameters, + _params: LimitTradeParametersFromQuote, networkCostsAmount = '0', checkEthFlowOrderExists?: EthFlowOrderExistsCallback ): Promise<{ txHash: string; orderId: string }> { diff --git a/src/trading/types.ts b/src/trading/types.ts index e0e56fde..bd1821f2 100644 --- a/src/trading/types.ts +++ b/src/trading/types.ts @@ -95,10 +95,14 @@ export interface LimitTradeParameters extends Omit { /** * Id of the quote to be used for the limit order. */ - quoteId: number + quoteId?: number validTo?: OrderParameters['validTo'] } +export interface LimitTradeParametersFromQuote extends LimitTradeParameters { + quoteId: number +} + export interface LimitOrderParameters extends TraderParameters, LimitTradeParameters {} export interface SwapAdvancedSettings { diff --git a/src/trading/utils.ts b/src/trading/utils.ts index a996e4bc..4e136d0e 100644 --- a/src/trading/utils.ts +++ b/src/trading/utils.ts @@ -1,4 +1,4 @@ -import { AccountAddress, LimitTradeParameters, PrivateKey, TradeParameters } from './types' +import { LimitTradeParametersFromQuote, PrivateKey, TradeParameters } from './types' import { QuoteAmountsAndCosts } from '../order-book' import { ETH_ADDRESS } from '../common' import { ethers, Signer } from 'ethers' @@ -8,7 +8,7 @@ export function swapParamsToLimitOrderParams( params: TradeParameters, quoteId: number, amounts: QuoteAmountsAndCosts -): LimitTradeParameters { +): LimitTradeParametersFromQuote { return { ...params, sellAmount: amounts.afterSlippage.sellAmount.toString(), @@ -33,10 +33,6 @@ export function getSigner(signer: Signer | ExternalProvider | PrivateKey): Signe return signer as Signer } -export function isAccountAddress(address: unknown): address is AccountAddress { - return typeof address === 'string' && /^0x[0-9a-fA-F]{40}$/.test(address) -} - /** * Returns the gas value plus a margin for unexpected or variable gas costs (20%) * @param value the gas value to pad From 6739150b7ad4fb6dc87e7a29a5a49fc889fba69f Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 5 Dec 2024 13:38:10 +0500 Subject: [PATCH 59/67] refactor: rename postOnChainTrade -> postSellNativeCurrencyTrade --- src/trading/README.md | 10 +++---- src/trading/index.ts | 2 +- src/trading/postCoWProtocolTrade.test.ts | 18 +++++------ src/trading/postCoWProtocolTrade.ts | 4 +-- ...ts => postSellNativeCurrencyTrade.test.ts} | 30 +++++++++++-------- ...rade.ts => postSellNativeCurrencyTrade.ts} | 2 +- src/trading/tradingSdk.ts | 8 ++--- 7 files changed, 40 insertions(+), 34 deletions(-) rename src/trading/{postOnChainTrade.test.ts => postSellNativeCurrencyTrade.test.ts} (87%) rename src/trading/{postOnChainTrade.ts => postSellNativeCurrencyTrade.ts} (95%) diff --git a/src/trading/README.md b/src/trading/README.md index 1ba42922..1470e6ac 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -55,7 +55,7 @@ The parameters required are: - `buyTokenDecimals` - the buy token decimals - `amount` - the amount to sell/buy in atoms -> When sell token is a blockchain native token (ETH for Ethereum), then order will be created as an on-chain transaction. See [postOnChainTrade](#postOnChainTrade) +> When sell token is a blockchain native token (ETH for Ethereum), then order will be created as an on-chain transaction. See [postSellNativeCurrencyTrade](#postSellNativeCurrencyTrade) #### Example @@ -186,14 +186,14 @@ const orderId = await sdk.postLimitOrder(limitOrderParameters) console.log('Order created, id: ', orderId) ``` -### postOnChainTrade +### postSellNativeCurrencyTrade CoW Protocol supports on-chain trades for selling blockchain native tokens (ETH for Ethereum). In this case, the order is created as an on-chain transaction. You don't have to think about the case when you use `postSwapOrder` function, it will be handled automatically. -But if you need more flexible way to create an on-chain order, you can use the `postOnChainTrade` function. +But if you need more flexible way to create an order to sell native token, you can use the `postSellNativeCurrencyTrade` function. -> We consider the order as an on-chain trade if the sell token has '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' address. +> We consider the order as native token selling order if the sell token has '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' address. ```typescript import { @@ -218,7 +218,7 @@ const parameters: TradeParameters = { amount: '120000000000000000' } -const orderId = await sdk.postOnChainTrade(parameters) +const orderId = await sdk.postSellNativeCurrencyTrade(parameters) console.log('Order created, id: ', orderId) ``` diff --git a/src/trading/index.ts b/src/trading/index.ts index da6b16c8..d05770ff 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -9,7 +9,7 @@ export { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' export { postLimitOrder } from './postLimitOrder' export { postCoWProtocolTrade } from './postCoWProtocolTrade' export { getOrderToSign } from './getOrderToSign' -export { postOnChainTrade } from './postOnChainTrade' +export { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' export { getEthFlowTransaction } from './getEthFlowTransaction' export { getPreSignTransaction } from './getPreSignTransaction' diff --git a/src/trading/postCoWProtocolTrade.test.ts b/src/trading/postCoWProtocolTrade.test.ts index 2f4f7ad7..6194bf5c 100644 --- a/src/trading/postCoWProtocolTrade.test.ts +++ b/src/trading/postCoWProtocolTrade.test.ts @@ -20,13 +20,13 @@ jest.mock('../order-signing', () => { } }) -jest.mock('./postOnChainTrade', () => { +jest.mock('./postSellNativeCurrencyTrade', () => { return { - postOnChainTrade: jest.fn(), + postSellNativeCurrencyTrade: jest.fn(), } }) -import { postOnChainTrade } from './postOnChainTrade' +import { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' import { AppDataInfo, LimitOrderParameters } from './types' import { ETH_ADDRESS, SupportedChainId } from '../common' @@ -68,11 +68,11 @@ const appDataMock = { describe('postCoWProtocolTrade', () => { let signOrderMock: jest.SpyInstance - let postOnChainTradeMock: jest.SpyInstance + let postSellNativeCurrencyTradeMock: jest.SpyInstance beforeAll(() => { signOrderMock = OrderSigningUtilsMock.signOrder as unknown as jest.SpyInstance - postOnChainTradeMock = postOnChainTrade as unknown as jest.SpyInstance + postSellNativeCurrencyTradeMock = postSellNativeCurrencyTrade as unknown as jest.SpyInstance }) beforeEach(() => { @@ -82,18 +82,18 @@ describe('postCoWProtocolTrade', () => { afterEach(() => { signOrderMock.mockReset() - postOnChainTradeMock.mockReset() + postSellNativeCurrencyTradeMock.mockReset() sendOrderMock.mockReset() }) it('When sell token is native, then should post on-chain order', async () => { - postOnChainTradeMock.mockResolvedValue({ orderId: '0x01' }) + postSellNativeCurrencyTradeMock.mockResolvedValue({ orderId: '0x01' }) const order = { ...defaultOrderParams, sellToken: ETH_ADDRESS } await postCoWProtocolTrade(orderBookApiMock, signer, appDataMock, order) - expect(postOnChainTradeMock).toHaveBeenCalledTimes(1) - expect(postOnChainTradeMock).toHaveBeenCalledWith(orderBookApiMock, signer, appDataMock, order, '0') + expect(postSellNativeCurrencyTradeMock).toHaveBeenCalledTimes(1) + expect(postSellNativeCurrencyTradeMock).toHaveBeenCalledWith(orderBookApiMock, signer, appDataMock, order, '0') }) it('API request should contain all specified parameters', async () => { diff --git a/src/trading/postCoWProtocolTrade.ts b/src/trading/postCoWProtocolTrade.ts index 4985a0f4..e9dbcb21 100644 --- a/src/trading/postCoWProtocolTrade.ts +++ b/src/trading/postCoWProtocolTrade.ts @@ -4,7 +4,7 @@ import { AppDataInfo, LimitTradeParameters } from './types' import { log, SIGN_SCHEME_MAP } from './consts' import { OrderSigningUtils } from '../order-signing' import { getOrderToSign } from './getOrderToSign' -import { postOnChainTrade } from './postOnChainTrade' +import { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' import { getIsEthFlowOrder } from './utils' export async function postCoWProtocolTrade( @@ -18,7 +18,7 @@ export async function postCoWProtocolTrade( const quoteId = params.quoteId if (typeof quoteId === 'number') { - const { orderId } = await postOnChainTrade( + const { orderId } = await postSellNativeCurrencyTrade( orderBookApi, signer, appData, diff --git a/src/trading/postOnChainTrade.test.ts b/src/trading/postSellNativeCurrencyTrade.test.ts similarity index 87% rename from src/trading/postOnChainTrade.test.ts rename to src/trading/postSellNativeCurrencyTrade.test.ts index e9296182..18a813a2 100644 --- a/src/trading/postOnChainTrade.test.ts +++ b/src/trading/postSellNativeCurrencyTrade.test.ts @@ -1,4 +1,9 @@ import { EthFlow__factory } from '../common/generated' +import { VoidSigner } from '@ethersproject/abstract-signer' +import { AppDataInfo, LimitOrderParameters } from './types' +import { SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' +import { OrderBookApi, OrderKind } from '../order-book' +import { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' jest.mock('cross-fetch', () => { // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -23,13 +28,7 @@ jest.mock('../common/generated', () => { } }) -import { VoidSigner } from '@ethersproject/abstract-signer' -import { AppDataInfo, LimitOrderParameters } from './types' -import { SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' -import { OrderBookApi, OrderKind } from '../order-book' -import { postOnChainTrade } from './postOnChainTrade' - -const defaultOrderParams: LimitOrderParameters = { +const defaultOrderParams: LimitOrderParameters & { quoteId: number } = { chainId: SupportedChainId.GNOSIS_CHAIN, signer: '1bb337bafb276f779c3035874b8914e4b851bb989dbb34e776397076576f3804', appCode: '0x007', @@ -72,7 +71,7 @@ const ethFlowContractMock = { }, } -describe('postOnChainTrade', () => { +describe('postSellNativeCurrencyTrade', () => { beforeAll(() => { ethFlowContractFactoryMock = EthFlow__factory.connect as unknown as jest.SpyInstance }) @@ -98,13 +97,20 @@ describe('postOnChainTrade', () => { it('Should call checkEthFlowOrderExists if it is set', async () => { const checkEthFlowOrderExists = jest.fn().mockResolvedValue(false) - await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams, '0', checkEthFlowOrderExists) + await postSellNativeCurrencyTrade( + orderBookApiMock, + signer, + appDataMock, + defaultOrderParams, + '0', + checkEthFlowOrderExists + ) expect(checkEthFlowOrderExists).toHaveBeenCalledTimes(1) }) it('Should upload appData', async () => { - await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) + await postSellNativeCurrencyTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) expect(uploadAppDataMock).toHaveBeenCalledWith(appDataMock.appDataKeccak256, appDataMock.fullAppData) }) @@ -112,7 +118,7 @@ describe('postOnChainTrade', () => { it('When transaction gas estimation is failed, then should use fallback value + 20%', async () => { ethFlowContractMock.estimateGas.createOrder.mockRejectedValue(new Error('Estimation failed')) - await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) + await postSellNativeCurrencyTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) const call = (signer.sendTransaction as jest.Mock).mock.calls[0][0] @@ -120,7 +126,7 @@ describe('postOnChainTrade', () => { }) it('Should create an on-chain transaction with all specified parameters', async () => { - await postOnChainTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) + await postSellNativeCurrencyTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) expect(ethFlowContractMock.interface.encodeFunctionData).toHaveBeenCalledTimes(1) expect(ethFlowContractMock.interface.encodeFunctionData).toHaveBeenCalledWith('createOrder', [ diff --git a/src/trading/postOnChainTrade.ts b/src/trading/postSellNativeCurrencyTrade.ts similarity index 95% rename from src/trading/postOnChainTrade.ts rename to src/trading/postSellNativeCurrencyTrade.ts index 8c186216..170e1922 100644 --- a/src/trading/postOnChainTrade.ts +++ b/src/trading/postSellNativeCurrencyTrade.ts @@ -6,7 +6,7 @@ import { log } from './consts' import { OrderBookApi } from '../order-book' import { getEthFlowTransaction } from './getEthFlowTransaction' -export async function postOnChainTrade( +export async function postSellNativeCurrencyTrade( orderBookApi: OrderBookApi, signer: Signer, appData: Pick, diff --git a/src/trading/tradingSdk.ts b/src/trading/tradingSdk.ts index 3bc4df92..a543a6e5 100644 --- a/src/trading/tradingSdk.ts +++ b/src/trading/tradingSdk.ts @@ -9,7 +9,7 @@ import { import { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' import { postLimitOrder } from './postLimitOrder' import { getQuoteWithSigner } from './getQuote' -import { postOnChainTrade } from './postOnChainTrade' +import { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' import { swapParamsToLimitOrderParams } from './utils' export class TradingSdk { @@ -23,14 +23,14 @@ export class TradingSdk { return postLimitOrder(this.mergeParams(params), advancedSettings) } - async postOnChainTrade( + async postSellNativeCurrencyTrade( params: TradeParameters, advancedSettings?: SwapAdvancedSettings - ): Promise> { + ): Promise> { const quoteResults = await getQuoteWithSigner(this.mergeParams(params), advancedSettings) const { tradeParameters, quoteResponse, amountsAndCosts } = quoteResults.result - return postOnChainTrade( + return postSellNativeCurrencyTrade( quoteResults.orderBookApi, quoteResults.result.signer, quoteResults.result.appDataInfo, From bb31db36952dad73f38290db8fc9047be6a907e6 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 5 Dec 2024 13:52:52 +0500 Subject: [PATCH 60/67] docs: optional params --- src/trading/README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/trading/README.md b/src/trading/README.md index 1470e6ac..3767f35d 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -223,6 +223,49 @@ const orderId = await sdk.postSellNativeCurrencyTrade(parameters) console.log('Order created, id: ', orderId) ``` +### Optional parameters + +Both `postSwapOrder` and `postLimitOrder` functions have optional parameters. +See `TradeOptionalParameters` type for more details. + +| **Parameter** | **Type** | **Default Value** | **Description** | +|-----------------------|-----------------|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `env` | `Env` | `prod` | The environment to use (`prod` or `staging`). | +| `partiallyFillable` | `boolean` | `false` | Indicates whether the order is fill-or-kill or partially fillable. | +| `slippageBps` | `number` | 0 | Slippage tolerance applied to the order to get the limit price. Expressed in Basis Points (BPS). One basis point is equivalent to 0.01% (1/100th of a percent). | +| `receiver` | `string` | order creator | The address that will receive the order's tokens. | +| `validFor` | `number` | 10 mins | The order expiration time in seconds. | +| `partnerFee` | `PartnerFee` | - | Partners of the protocol can specify their fee for the order, including the fee in basis points (BPS) and the fee recipient address. [Read more](https://docs.cow.fi/governance/fees/partner-fee) | + +##### Example + +```typescript +import { SupportedChainId, OrderKind, TradeParameters, TradingSdk } from '@cowprotocol/cow-sdk' + +const sdk = new TradingSdk({ + chainId: SupportedChainId.SEPOLIA, + signer: '', + appCode: '', +}) + +const parameters: TradeParameters = { + kind: OrderKind.BUY, + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '120000000000000000', + // Optional parameters + slippageBps: 200, // 2% + validFor: 1200, // 20 mins + receiver: '0xdef1ca1fb7f1232777520aa7f396b4e015f497ab' // Just a random address, don't use it! +} + +const orderId = await sdk.postSwapOrder(parameters) + +console.log('Order created, id: ', orderId) +``` + ### Advanced swap order creation By default, the SDK requires only the basic parameters to create an order. From da3749caed2954ef999ec55e4f5699d2512bd209 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 5 Dec 2024 14:04:22 +0500 Subject: [PATCH 61/67] chore: fix tests --- src/trading/getPreSignTransaction.test.ts | 2 +- src/trading/getQuote.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/trading/getPreSignTransaction.test.ts b/src/trading/getPreSignTransaction.test.ts index 84cb496c..980fd4d3 100644 --- a/src/trading/getPreSignTransaction.test.ts +++ b/src/trading/getPreSignTransaction.test.ts @@ -49,7 +49,7 @@ describe('getPreSignTransaction', () => { const result = await getPreSignTransaction(signer, chainId, account, orderId) const gasNum = +GAS - expect(+result.gas).toBe(gasNum + gasNum * 0.2) + expect(+result.gas).toBe(gasNum * 1.2) }) it('Tx value should always be zero', async () => { diff --git a/src/trading/getQuote.test.ts b/src/trading/getQuote.test.ts index 666a3118..b2c0d0ee 100644 --- a/src/trading/getQuote.test.ts +++ b/src/trading/getQuote.test.ts @@ -139,10 +139,10 @@ describe('getQuoteToSign', () => { describe('Amounts and costs', () => { it('Should take slippage value into account', async () => { const { result } = await getQuoteWithSigner({ ...defaultOrderParams, slippageBps: 20 }, {}, orderBookApiMock) - const buyAmount = quoteResponseMock.quote.buyAmount + const buyAmount = +quoteResponseMock.quote.buyAmount expect(+result.amountsAndCosts.afterSlippage.buyAmount.toString()).toBe( - +buyAmount - (+buyAmount * 20) / (100 * 100) + buyAmount - (buyAmount * 20) / (100 * 100) ) }) it('Should calculate network costs based on quote API response', async () => { From 61aad12d3453b585ca7c2be3e3b8d5b6000a77f9 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 5 Dec 2024 14:04:39 +0500 Subject: [PATCH 62/67] fix: add additional params for eth-flow quote req --- src/trading/getQuote.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/trading/getQuote.ts b/src/trading/getQuote.ts index d7daa756..41c6b58f 100644 --- a/src/trading/getQuote.ts +++ b/src/trading/getQuote.ts @@ -24,6 +24,16 @@ import { Signer } from 'ethers' import { WRAPPED_NATIVE_CURRENCIES } from '../common' import { getOrderTypedData } from './getOrderTypedData' +// ETH-FLOW orders require different quote params +// check the isEthFlow flag and set in quote req obj +const ETH_FLOW_AUX_QUOTE_PARAMS = { + signingScheme: SigningScheme.EIP1271, + onchainOrder: true, + // Ethflow orders are subsidized in the backend. + // This means we can assume the verification gas costs are zero for the quote/fee estimation + verificationGasLimit: 0, +} + export type QuoteResultsWithSigner = { result: QuoteResults & { signer: Signer }; orderBookApi: OrderBookApi } export async function getQuote( @@ -33,8 +43,9 @@ export async function getQuote( _orderBookApi?: OrderBookApi ): Promise<{ result: QuoteResults; orderBookApi: OrderBookApi }> { const { appCode, chainId, account: from } = trader + const isEthFlow = getIsEthFlowOrder(_tradeParameters) - const tradeParameters = getIsEthFlowOrder(_tradeParameters) + const tradeParameters = isEthFlow ? { ..._tradeParameters, sellToken: WRAPPED_NATIVE_CURRENCIES[chainId], @@ -84,6 +95,7 @@ export async function getQuote( appDataHash: appDataKeccak256, priceQuality: PriceQuality.OPTIMAL, // Do not change this parameter because we rely on the fact that quote has id signingScheme: SigningScheme.EIP712, + ...(isEthFlow ? ETH_FLOW_AUX_QUOTE_PARAMS : {}), ...(isSell ? { kind: OrderQuoteSideKindSell.SELL, sellAmountBeforeFee: amount } : { kind: OrderQuoteSideKindBuy.BUY, buyAmountAfterFee: amount }), From cc7b2b414d7ed6281d1be418675bc672d1c69a6a Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 5 Dec 2024 14:10:26 +0500 Subject: [PATCH 63/67] feat: add getPreSignTransaction to TradingSdk --- src/trading/tradingSdk.ts | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/trading/tradingSdk.ts b/src/trading/tradingSdk.ts index a543a6e5..5def5c01 100644 --- a/src/trading/tradingSdk.ts +++ b/src/trading/tradingSdk.ts @@ -10,11 +10,21 @@ import { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' import { postLimitOrder } from './postLimitOrder' import { getQuoteWithSigner } from './getQuote' import { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' -import { swapParamsToLimitOrderParams } from './utils' +import { getSigner, swapParamsToLimitOrderParams } from './utils' +import { getPreSignTransaction } from './getPreSignTransaction' export class TradingSdk { constructor(public readonly traderParams: TraderParameters) {} + async getQuote(params: TradeParameters, advancedSettings?: SwapAdvancedSettings): Promise { + const quoteResults = await getQuoteWithSigner(this.mergeParams(params), advancedSettings) + + return { + quoteResults: quoteResults.result, + postSwapOrderFromQuote: () => postSwapOrderFromQuote(quoteResults), + } + } + async postSwapOrder(params: TradeParameters, advancedSettings?: SwapAdvancedSettings): Promise { return postSwapOrder(this.mergeParams(params), advancedSettings) } @@ -34,18 +44,16 @@ export class TradingSdk { quoteResults.orderBookApi, quoteResults.result.signer, quoteResults.result.appDataInfo, + // Quote response response always has an id // eslint-disable-next-line @typescript-eslint/no-non-null-assertion swapParamsToLimitOrderParams(tradeParameters, quoteResponse.id!, amountsAndCosts) ) } - async getQuote(params: TradeParameters, advancedSettings?: SwapAdvancedSettings): Promise { - const quoteResults = await getQuoteWithSigner(this.mergeParams(params), advancedSettings) + async getPreSignTransaction(params: { orderId: string; account: string }): ReturnType { + const signer = getSigner(this.traderParams.signer) - return { - quoteResults: quoteResults.result, - postSwapOrderFromQuote: () => postSwapOrderFromQuote(quoteResults), - } + return getPreSignTransaction(signer, this.traderParams.chainId, params.account, params.orderId) } private mergeParams(params: T): T & TraderParameters { From b21a9f8a405002aaeef307e00140945d03ecda63 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 5 Dec 2024 14:57:48 +0500 Subject: [PATCH 64/67] docs: get quest for smart-contract wallet --- src/trading/README.md | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/trading/README.md b/src/trading/README.md index 3767f35d..cb485108 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -140,6 +140,50 @@ if (confirm(`You will get at least: ${buyAmount}, ok?`)) { } ``` +### Get quote for a smart-contract wallet + +If you want to use a smart-contract wallet to sign the order, you should specify the `signingScheme` parameter in order to get more accurate quote in terms of gas efficiency. +Smart-contract wallets are supported by using a different signing scheme - `SigningScheme.PRESIGN`. + +#### Example + +```typescript +import { + SupportedChainId, + OrderKind, + TradeParameters, + SwapAdvancedSettings, + SigningScheme, + TradingSdk +} from '@cowprotocol/cow-sdk' + +const sdk = new TradingSdk({ + chainId: SupportedChainId.SEPOLIA, + signer: '', + appCode: '', +}) + +const parameters: TradeParameters = { + kind: OrderKind.BUY, + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '120000000000000000' +} + +const advancedParameters: SwapAdvancedSettings = { + quoteRequest: { + // Specify the signing scheme + signingScheme: SigningScheme.PRESIGN + } +} + +const { quoteResults } = await sdk.getQuote(parameters) + +console.log('Quote:', quoteResults) +```` + ### postLimitOrder This main difference between this function and `postSwapOrder` is that here you need to specify both sell and buy amounts. From 6fc34fd46128106a84ecae754bdd7afc9ba7043b Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 5 Dec 2024 15:41:26 +0500 Subject: [PATCH 65/67] chore: rename postSellNativeCurrencyOrder --- src/trading/README.md | 8 +++---- src/trading/index.ts | 2 +- src/trading/postCoWProtocolTrade.test.ts | 22 +++++++++---------- src/trading/postCoWProtocolTrade.ts | 4 ++-- ...ts => postSellNativeCurrencyOrder.test.ts} | 10 ++++----- ...rade.ts => postSellNativeCurrencyOrder.ts} | 2 +- src/trading/tradingSdk.ts | 8 +++---- 7 files changed, 28 insertions(+), 28 deletions(-) rename src/trading/{postSellNativeCurrencyTrade.test.ts => postSellNativeCurrencyOrder.test.ts} (94%) rename src/trading/{postSellNativeCurrencyTrade.ts => postSellNativeCurrencyOrder.ts} (95%) diff --git a/src/trading/README.md b/src/trading/README.md index cb485108..2079b362 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -55,7 +55,7 @@ The parameters required are: - `buyTokenDecimals` - the buy token decimals - `amount` - the amount to sell/buy in atoms -> When sell token is a blockchain native token (ETH for Ethereum), then order will be created as an on-chain transaction. See [postSellNativeCurrencyTrade](#postSellNativeCurrencyTrade) +> When sell token is a blockchain native token (ETH for Ethereum), then order will be created as an on-chain transaction. See [postSellNativeCurrencyOrder](#postSellNativeCurrencyOrder) #### Example @@ -230,12 +230,12 @@ const orderId = await sdk.postLimitOrder(limitOrderParameters) console.log('Order created, id: ', orderId) ``` -### postSellNativeCurrencyTrade +### postSellNativeCurrencyOrder CoW Protocol supports on-chain trades for selling blockchain native tokens (ETH for Ethereum). In this case, the order is created as an on-chain transaction. You don't have to think about the case when you use `postSwapOrder` function, it will be handled automatically. -But if you need more flexible way to create an order to sell native token, you can use the `postSellNativeCurrencyTrade` function. +But if you need more flexible way to create an order to sell native token, you can use the `postSellNativeCurrencyOrder` function. > We consider the order as native token selling order if the sell token has '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' address. @@ -262,7 +262,7 @@ const parameters: TradeParameters = { amount: '120000000000000000' } -const orderId = await sdk.postSellNativeCurrencyTrade(parameters) +const orderId = await sdk.postSellNativeCurrencyOrder(parameters) console.log('Order created, id: ', orderId) ``` diff --git a/src/trading/index.ts b/src/trading/index.ts index d05770ff..1cc5e8a1 100644 --- a/src/trading/index.ts +++ b/src/trading/index.ts @@ -9,7 +9,7 @@ export { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' export { postLimitOrder } from './postLimitOrder' export { postCoWProtocolTrade } from './postCoWProtocolTrade' export { getOrderToSign } from './getOrderToSign' -export { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' +export { postSellNativeCurrencyOrder } from './postSellNativeCurrencyOrder' export { getEthFlowTransaction } from './getEthFlowTransaction' export { getPreSignTransaction } from './getPreSignTransaction' diff --git a/src/trading/postCoWProtocolTrade.test.ts b/src/trading/postCoWProtocolTrade.test.ts index 6194bf5c..bb81d3cb 100644 --- a/src/trading/postCoWProtocolTrade.test.ts +++ b/src/trading/postCoWProtocolTrade.test.ts @@ -1,5 +1,3 @@ -import { postCoWProtocolTrade } from './postCoWProtocolTrade' - jest.mock('cross-fetch', () => { // eslint-disable-next-line @typescript-eslint/no-var-requires const fetchMock = require('jest-fetch-mock') @@ -20,13 +18,13 @@ jest.mock('../order-signing', () => { } }) -jest.mock('./postSellNativeCurrencyTrade', () => { +jest.mock('./postSellNativeCurrencyOrder', () => { return { postSellNativeCurrencyTrade: jest.fn(), } }) -import { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' +import { postSellNativeCurrencyOrder } from './postSellNativeCurrencyOrder' import { AppDataInfo, LimitOrderParameters } from './types' import { ETH_ADDRESS, SupportedChainId } from '../common' @@ -34,6 +32,8 @@ import { OrderBookApi, OrderKind } from '../order-book' import { OrderSigningUtils as OrderSigningUtilsMock } from '../order-signing' import { VoidSigner } from '@ethersproject/abstract-signer' +const quoteId = 31 + const defaultOrderParams: LimitOrderParameters = { chainId: SupportedChainId.GNOSIS_CHAIN, signer: '0x006', @@ -45,7 +45,7 @@ const defaultOrderParams: LimitOrderParameters = { sellAmount: '1000000000000000000', buyAmount: '2000000000000000000', kind: OrderKind.SELL, - quoteId: 31, + quoteId, slippageBps: 50, } @@ -66,13 +66,13 @@ const appDataMock = { '{\\"appCode\\":\\"CoW Swap\\",\\"environment\\":\\"barn\\",\\"metadata\\":{\\"orderClass\\":{\\"orderClass\\":\\"market\\"},\\"quote\\":{\\"slippageBips\\":201,\\"smartSlippage\\":true}},\\"version\\":\\"1.3.0\\"}', } as unknown as AppDataInfo -describe('postCoWProtocolTrade', () => { +describe('postSellNativeCurrencyOrder', () => { let signOrderMock: jest.SpyInstance let postSellNativeCurrencyTradeMock: jest.SpyInstance beforeAll(() => { signOrderMock = OrderSigningUtilsMock.signOrder as unknown as jest.SpyInstance - postSellNativeCurrencyTradeMock = postSellNativeCurrencyTrade as unknown as jest.SpyInstance + postSellNativeCurrencyTradeMock = postSellNativeCurrencyOrder as unknown as jest.SpyInstance }) beforeEach(() => { @@ -89,8 +89,8 @@ describe('postCoWProtocolTrade', () => { it('When sell token is native, then should post on-chain order', async () => { postSellNativeCurrencyTradeMock.mockResolvedValue({ orderId: '0x01' }) - const order = { ...defaultOrderParams, sellToken: ETH_ADDRESS } - await postCoWProtocolTrade(orderBookApiMock, signer, appDataMock, order) + const order = { ...defaultOrderParams, sellToken: ETH_ADDRESS, quoteId } + await postSellNativeCurrencyOrder(orderBookApiMock, signer, appDataMock, order) expect(postSellNativeCurrencyTradeMock).toHaveBeenCalledTimes(1) expect(postSellNativeCurrencyTradeMock).toHaveBeenCalledWith(orderBookApiMock, signer, appDataMock, order, '0') @@ -99,8 +99,8 @@ describe('postCoWProtocolTrade', () => { it('API request should contain all specified parameters', async () => { sendOrderMock.mockResolvedValue('0x02') - const order = { ...defaultOrderParams } - await postCoWProtocolTrade(orderBookApiMock, signer, appDataMock, order) + const order = { ...defaultOrderParams, quoteId } + await postSellNativeCurrencyOrder(orderBookApiMock, signer, appDataMock, order) const callBody = sendOrderMock.mock.calls[0][0] diff --git a/src/trading/postCoWProtocolTrade.ts b/src/trading/postCoWProtocolTrade.ts index e9dbcb21..098cabcf 100644 --- a/src/trading/postCoWProtocolTrade.ts +++ b/src/trading/postCoWProtocolTrade.ts @@ -4,7 +4,7 @@ import { AppDataInfo, LimitTradeParameters } from './types' import { log, SIGN_SCHEME_MAP } from './consts' import { OrderSigningUtils } from '../order-signing' import { getOrderToSign } from './getOrderToSign' -import { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' +import { postSellNativeCurrencyOrder } from './postSellNativeCurrencyOrder' import { getIsEthFlowOrder } from './utils' export async function postCoWProtocolTrade( @@ -18,7 +18,7 @@ export async function postCoWProtocolTrade( const quoteId = params.quoteId if (typeof quoteId === 'number') { - const { orderId } = await postSellNativeCurrencyTrade( + const { orderId } = await postSellNativeCurrencyOrder( orderBookApi, signer, appData, diff --git a/src/trading/postSellNativeCurrencyTrade.test.ts b/src/trading/postSellNativeCurrencyOrder.test.ts similarity index 94% rename from src/trading/postSellNativeCurrencyTrade.test.ts rename to src/trading/postSellNativeCurrencyOrder.test.ts index 18a813a2..308fbe3e 100644 --- a/src/trading/postSellNativeCurrencyTrade.test.ts +++ b/src/trading/postSellNativeCurrencyOrder.test.ts @@ -3,7 +3,7 @@ import { VoidSigner } from '@ethersproject/abstract-signer' import { AppDataInfo, LimitOrderParameters } from './types' import { SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from '../common' import { OrderBookApi, OrderKind } from '../order-book' -import { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' +import { postSellNativeCurrencyOrder } from './postSellNativeCurrencyOrder' jest.mock('cross-fetch', () => { // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -97,7 +97,7 @@ describe('postSellNativeCurrencyTrade', () => { it('Should call checkEthFlowOrderExists if it is set', async () => { const checkEthFlowOrderExists = jest.fn().mockResolvedValue(false) - await postSellNativeCurrencyTrade( + await postSellNativeCurrencyOrder( orderBookApiMock, signer, appDataMock, @@ -110,7 +110,7 @@ describe('postSellNativeCurrencyTrade', () => { }) it('Should upload appData', async () => { - await postSellNativeCurrencyTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) + await postSellNativeCurrencyOrder(orderBookApiMock, signer, appDataMock, defaultOrderParams) expect(uploadAppDataMock).toHaveBeenCalledWith(appDataMock.appDataKeccak256, appDataMock.fullAppData) }) @@ -118,7 +118,7 @@ describe('postSellNativeCurrencyTrade', () => { it('When transaction gas estimation is failed, then should use fallback value + 20%', async () => { ethFlowContractMock.estimateGas.createOrder.mockRejectedValue(new Error('Estimation failed')) - await postSellNativeCurrencyTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) + await postSellNativeCurrencyOrder(orderBookApiMock, signer, appDataMock, defaultOrderParams) const call = (signer.sendTransaction as jest.Mock).mock.calls[0][0] @@ -126,7 +126,7 @@ describe('postSellNativeCurrencyTrade', () => { }) it('Should create an on-chain transaction with all specified parameters', async () => { - await postSellNativeCurrencyTrade(orderBookApiMock, signer, appDataMock, defaultOrderParams) + await postSellNativeCurrencyOrder(orderBookApiMock, signer, appDataMock, defaultOrderParams) expect(ethFlowContractMock.interface.encodeFunctionData).toHaveBeenCalledTimes(1) expect(ethFlowContractMock.interface.encodeFunctionData).toHaveBeenCalledWith('createOrder', [ diff --git a/src/trading/postSellNativeCurrencyTrade.ts b/src/trading/postSellNativeCurrencyOrder.ts similarity index 95% rename from src/trading/postSellNativeCurrencyTrade.ts rename to src/trading/postSellNativeCurrencyOrder.ts index 170e1922..66692338 100644 --- a/src/trading/postSellNativeCurrencyTrade.ts +++ b/src/trading/postSellNativeCurrencyOrder.ts @@ -6,7 +6,7 @@ import { log } from './consts' import { OrderBookApi } from '../order-book' import { getEthFlowTransaction } from './getEthFlowTransaction' -export async function postSellNativeCurrencyTrade( +export async function postSellNativeCurrencyOrder( orderBookApi: OrderBookApi, signer: Signer, appData: Pick, diff --git a/src/trading/tradingSdk.ts b/src/trading/tradingSdk.ts index 5def5c01..735b18b1 100644 --- a/src/trading/tradingSdk.ts +++ b/src/trading/tradingSdk.ts @@ -9,7 +9,7 @@ import { import { postSwapOrder, postSwapOrderFromQuote } from './postSwapOrder' import { postLimitOrder } from './postLimitOrder' import { getQuoteWithSigner } from './getQuote' -import { postSellNativeCurrencyTrade } from './postSellNativeCurrencyTrade' +import { postSellNativeCurrencyOrder } from './postSellNativeCurrencyOrder' import { getSigner, swapParamsToLimitOrderParams } from './utils' import { getPreSignTransaction } from './getPreSignTransaction' @@ -33,14 +33,14 @@ export class TradingSdk { return postLimitOrder(this.mergeParams(params), advancedSettings) } - async postSellNativeCurrencyTrade( + async postSellNativeCurrencyOrder( params: TradeParameters, advancedSettings?: SwapAdvancedSettings - ): Promise> { + ): Promise> { const quoteResults = await getQuoteWithSigner(this.mergeParams(params), advancedSettings) const { tradeParameters, quoteResponse, amountsAndCosts } = quoteResults.result - return postSellNativeCurrencyTrade( + return postSellNativeCurrencyOrder( quoteResults.orderBookApi, quoteResults.result.signer, quoteResults.result.appDataInfo, From 31b149869162df2303fa82841ab99e9ad0d806d9 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Wed, 11 Dec 2024 13:34:12 +0500 Subject: [PATCH 66/67] docs: create an order with smart-contract wallet --- src/trading/README.md | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/trading/README.md b/src/trading/README.md index 2079b362..a113ed94 100644 --- a/src/trading/README.md +++ b/src/trading/README.md @@ -184,6 +184,52 @@ const { quoteResults } = await sdk.getQuote(parameters) console.log('Quote:', quoteResults) ```` +### Create an order with smart-contract wallet + +If you want to create an order with a smart-contract wallet, you should specify the `signingScheme` parameter in the `postSwapOrder` function. +And then you need to send a transaction from `getPreSignTransaction` result in order to sign the order. + +#### Example + +```typescript +import { + SupportedChainId, + OrderKind, + TradeParameters, + TradingSdk +} from '@cowprotocol/cow-sdk' + +const sdk = new TradingSdk({ + chainId: SupportedChainId.SEPOLIA, + signer: '', + appCode: '', +}) + +const parameters: TradeParameters = { + kind: OrderKind.BUY, + sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14', + sellTokenDecimals: 18, + buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59', + buyTokenDecimals: 18, + amount: '120000000000000000' +} + +const advancedParameters: SwapAdvancedSettings = { + quoteRequest: { + // Specify the signing scheme + signingScheme: SigningScheme.PRESIGN + } +} + +const smartContractWalletAddress = '0x' +const orderId = await sdk.postSwapOrder(parameters, advancedParameters) +const preSignTransaction = await sdk.getPreSignTransaction({ orderId, account: smartContractWalletAddress }) + +console.log('Order created with "pre-sign" state, id: ', orderId) +console.log('Execute the transaction to sign the order', preSignTransaction) +``` + + ### postLimitOrder This main difference between this function and `postSwapOrder` is that here you need to specify both sell and buy amounts. From eec09d4927789b1e19b4eb1af7b0d69100cb3312 Mon Sep 17 00:00:00 2001 From: shoom3301 Date: Thu, 12 Dec 2024 12:13:40 +0500 Subject: [PATCH 67/67] chore: fix tests --- src/trading/postCoWProtocolTrade.test.ts | 29 ++++++++++++------------ 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/trading/postCoWProtocolTrade.test.ts b/src/trading/postCoWProtocolTrade.test.ts index bb81d3cb..dcc373b2 100644 --- a/src/trading/postCoWProtocolTrade.test.ts +++ b/src/trading/postCoWProtocolTrade.test.ts @@ -20,10 +20,11 @@ jest.mock('../order-signing', () => { jest.mock('./postSellNativeCurrencyOrder', () => { return { - postSellNativeCurrencyTrade: jest.fn(), + postSellNativeCurrencyOrder: jest.fn(), } }) +import { postCoWProtocolTrade } from './postCoWProtocolTrade' import { postSellNativeCurrencyOrder } from './postSellNativeCurrencyOrder' import { AppDataInfo, LimitOrderParameters } from './types' @@ -32,8 +33,6 @@ import { OrderBookApi, OrderKind } from '../order-book' import { OrderSigningUtils as OrderSigningUtilsMock } from '../order-signing' import { VoidSigner } from '@ethersproject/abstract-signer' -const quoteId = 31 - const defaultOrderParams: LimitOrderParameters = { chainId: SupportedChainId.GNOSIS_CHAIN, signer: '0x006', @@ -45,7 +44,7 @@ const defaultOrderParams: LimitOrderParameters = { sellAmount: '1000000000000000000', buyAmount: '2000000000000000000', kind: OrderKind.SELL, - quoteId, + quoteId: 31, slippageBps: 50, } @@ -66,13 +65,13 @@ const appDataMock = { '{\\"appCode\\":\\"CoW Swap\\",\\"environment\\":\\"barn\\",\\"metadata\\":{\\"orderClass\\":{\\"orderClass\\":\\"market\\"},\\"quote\\":{\\"slippageBips\\":201,\\"smartSlippage\\":true}},\\"version\\":\\"1.3.0\\"}', } as unknown as AppDataInfo -describe('postSellNativeCurrencyOrder', () => { +describe('postCoWProtocolTrade', () => { let signOrderMock: jest.SpyInstance - let postSellNativeCurrencyTradeMock: jest.SpyInstance + let postSellNativeCurrencyOrderMock: jest.SpyInstance beforeAll(() => { signOrderMock = OrderSigningUtilsMock.signOrder as unknown as jest.SpyInstance - postSellNativeCurrencyTradeMock = postSellNativeCurrencyOrder as unknown as jest.SpyInstance + postSellNativeCurrencyOrderMock = postSellNativeCurrencyOrder as unknown as jest.SpyInstance }) beforeEach(() => { @@ -82,25 +81,25 @@ describe('postSellNativeCurrencyOrder', () => { afterEach(() => { signOrderMock.mockReset() - postSellNativeCurrencyTradeMock.mockReset() + postSellNativeCurrencyOrderMock.mockReset() sendOrderMock.mockReset() }) it('When sell token is native, then should post on-chain order', async () => { - postSellNativeCurrencyTradeMock.mockResolvedValue({ orderId: '0x01' }) + postSellNativeCurrencyOrderMock.mockResolvedValue({ orderId: '0x01' }) - const order = { ...defaultOrderParams, sellToken: ETH_ADDRESS, quoteId } - await postSellNativeCurrencyOrder(orderBookApiMock, signer, appDataMock, order) + const order = { ...defaultOrderParams, sellToken: ETH_ADDRESS } + await postCoWProtocolTrade(orderBookApiMock, signer, appDataMock, order) - expect(postSellNativeCurrencyTradeMock).toHaveBeenCalledTimes(1) - expect(postSellNativeCurrencyTradeMock).toHaveBeenCalledWith(orderBookApiMock, signer, appDataMock, order, '0') + expect(postSellNativeCurrencyOrderMock).toHaveBeenCalledTimes(1) + expect(postSellNativeCurrencyOrderMock).toHaveBeenCalledWith(orderBookApiMock, signer, appDataMock, order, '0') }) it('API request should contain all specified parameters', async () => { sendOrderMock.mockResolvedValue('0x02') - const order = { ...defaultOrderParams, quoteId } - await postSellNativeCurrencyOrder(orderBookApiMock, signer, appDataMock, order) + const order = { ...defaultOrderParams } + await postCoWProtocolTrade(orderBookApiMock, signer, appDataMock, order) const callBody = sendOrderMock.mock.calls[0][0]