From 4fd4f5d9bdc2d6b6af3f4645c9907d5bde7bb2ac Mon Sep 17 00:00:00 2001 From: Kai Hirota <34954529+kaihirota@users.noreply.github.com> Date: Mon, 26 Feb 2024 14:51:50 +1100 Subject: [PATCH] CORE-1942 Add prepare withdrawal v2 workflow (#402) * update OpenAPI generated API client code * add prepare withdrawal v2 workflow * fix typo * update error message * rename vars * update * update * fix bad refs --- examples/package.json | 2 +- openapi.json | 16 +++--- src/workflows/withdrawal/prepareWithdrawal.ts | 54 +++++++++++++++++++ src/workflows/workflows.ts | 36 +++++++++++-- 4 files changed, 94 insertions(+), 14 deletions(-) diff --git a/examples/package.json b/examples/package.json index 2b4420ea..98a814db 100644 --- a/examples/package.json +++ b/examples/package.json @@ -48,7 +48,7 @@ "create-nft-withdrawal": "ts-node -r dotenv/config createNftWithdrawal.ts", "complete-nft-withdrawal": "ts-node -r dotenv/config completeNftWithdrawal.ts", "complete-erc20-withdrawal": "ts-node -r dotenv/config completeErc20Withdrawal.ts", - "create-erc20-withdrawal": "ts-node -r dotenv/config completeErc20Withdrawal.ts", + "create-erc20-withdrawal": "ts-node -r dotenv/config createErc20Withdrawal.ts", "list-collections": "ts-node -r dotenv/config listCollections.ts", "list-collection-filters": "ts-node -r dotenv/config listCollectionFilters.ts", "update-collection": "ts-node -r dotenv/config updateCollection.ts" diff --git a/openapi.json b/openapi.json index 40b8fed1..396b73da 100644 --- a/openapi.json +++ b/openapi.json @@ -14003,7 +14003,7 @@ "content": { "application/json": { "schema": { - "$ref": "../../../../common/openapi/errors/api_errors_v2.yaml#/definitions/APIError400" + "$ref": "#/definitions/APIError" } } }, @@ -14013,7 +14013,7 @@ "content": { "application/json": { "schema": { - "$ref": "../../../../common/openapi/errors/api_errors_v2.yaml#/definitions/APIError403" + "$ref": "#/definitions/APIError" } } }, @@ -14023,7 +14023,7 @@ "content": { "application/json": { "schema": { - "$ref": "../../../../common/openapi/errors/api_errors_v2.yaml#/definitions/APIError500" + "$ref": "#/definitions/APIError" } } }, @@ -14033,7 +14033,7 @@ "content": { "application/json": { "schema": { - "$ref": "../../../../common/openapi/errors/api_errors_v2.yaml#/definitions/APIError404" + "$ref": "#/definitions/APIError" } } }, @@ -14043,7 +14043,7 @@ "content": { "application/json": { "schema": { - "$ref": "../../../../common/openapi/errors/api_errors_v2.yaml#/definitions/APIError501" + "$ref": "#/definitions/APIError" } } }, @@ -14053,7 +14053,7 @@ "content": { "application/json": { "schema": { - "$ref": "../../../../common/openapi/errors/api_errors_v2.yaml#/definitions/APIError429" + "$ref": "#/definitions/APIError" } } }, @@ -14063,7 +14063,7 @@ "content": { "application/json": { "schema": { - "$ref": "../../../../common/openapi/errors/api_errors_v2.yaml#/definitions/APIError401" + "$ref": "#/definitions/APIError" } } }, @@ -14073,7 +14073,7 @@ "content": { "application/json": { "schema": { - "$ref": "../../../../common/openapi/errors/api_errors_v2.yaml#/definitions/APIError422" + "$ref": "#/definitions/APIError" } } }, diff --git a/src/workflows/withdrawal/prepareWithdrawal.ts b/src/workflows/withdrawal/prepareWithdrawal.ts index fae7cc21..d41cdb67 100644 --- a/src/workflows/withdrawal/prepareWithdrawal.ts +++ b/src/workflows/withdrawal/prepareWithdrawal.ts @@ -51,3 +51,57 @@ export async function prepareWithdrawalWorkflow( return prepareWithdrawalResponse.data; } + +export async function prepareWithdrawalV2Workflow( + params: PrepareWithdrawalWorkflowParams, +): Promise { + const { ethSigner, starkSigner, withdrawalsApi } = params; + const withdrawalAmount = params.type === 'ERC721' ? '1' : params.amount; + const signableWithdrawalResult = await withdrawalsApi.getSignableWithdrawalV2( + { + getSignableWithdrawalRequest: { + user: await ethSigner.getAddress(), + token: convertToSignableToken(params), + amount: withdrawalAmount, + }, + }, + ); + + const { signable_message: signableMessage, payload_hash: payloadHash } = + signableWithdrawalResult.data; + + const starkSignature = await starkSigner.signMessage(payloadHash); + + const { ethAddress, ethSignature } = await signMessage( + signableMessage, + ethSigner, + ); + + const prepareWithdrawalResponse = await withdrawalsApi.createWithdrawalV2({ + createWithdrawalRequestV2: { + sender_stark_key: assertIsDefined( + signableWithdrawalResult.data.sender_stark_key, + ), + sender_vault_id: assertIsDefined( + signableWithdrawalResult.data.sender_vault_id, + ), + receiver_stark_key: assertIsDefined( + signableWithdrawalResult.data.receiver_stark_key, + ), + receiver_vault_id: assertIsDefined( + signableWithdrawalResult.data.receiver_vault_id, + ), + amount: withdrawalAmount, + asset_id: assertIsDefined(signableWithdrawalResult.data.asset_id), + expiration_timestamp: assertIsDefined( + signableWithdrawalResult.data.expiration_timestamp, + ), + nonce: assertIsDefined(signableWithdrawalResult.data.nonce), + stark_signature: starkSignature, + }, + xImxEthAddress: ethAddress, + xImxEthSignature: ethSignature, + }); + + return prepareWithdrawalResponse.data; +} diff --git a/src/workflows/workflows.ts b/src/workflows/workflows.ts index 3e9713c0..df59a65f 100644 --- a/src/workflows/workflows.ts +++ b/src/workflows/workflows.ts @@ -56,6 +56,7 @@ import { completeERC20WithdrawalWorkflow, completeERC721WithdrawalWorkflow, completeEthWithdrawalWorkflow, + prepareWithdrawalV2Workflow, prepareWithdrawalWorkflow, } from './withdrawal'; import { cancelOrderWorkflow, createOrderWorkflow } from './orders'; @@ -254,11 +255,36 @@ export class Workflows { ) { await this.validateChain(walletConnection.ethSigner); - return prepareWithdrawalWorkflow({ - ...walletConnection, - ...request, - withdrawalsApi: this.withdrawalsApi, - }); + const starkExContractInfo = await this.getStarkExContractVersion(); + const majorContractVersion = await this.parseMajorContractVersion( + starkExContractInfo.data.version, + ); + + if (majorContractVersion === 3) { + return prepareWithdrawalWorkflow({ + ...walletConnection, + ...request, + withdrawalsApi: this.withdrawalsApi, + }); + } + + if (majorContractVersion >= 4) { + return prepareWithdrawalV2Workflow({ + ...walletConnection, + ...request, + withdrawalsApi: this.withdrawalsApi, + }); + } + + throw new Error( + `Invalid StarkEx contract version (${majorContractVersion}). Please try again later.`, + ); + } + + private async parseMajorContractVersion( + contractVersion: string, + ): Promise { + return parseInt(contractVersion.charAt(0)); } public completeWithdrawal(