From 663f1f69b90d9ecbc615a4c9d8f467e8b26371e9 Mon Sep 17 00:00:00 2001 From: Rustin Date: Sat, 28 Sep 2024 09:51:03 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=90=9B=20fix:=20icrc=20post=20message?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dfinity/post-message-transport-hook.ts | 63 +++++++++---------- apps/wallet/src/utils/chain/index.ts | 1 + 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/apps/wallet/src/utils/chain/chain-wallets/dfinity/post-message-transport-hook.ts b/apps/wallet/src/utils/chain/chain-wallets/dfinity/post-message-transport-hook.ts index 53ca6db..14acf90 100644 --- a/apps/wallet/src/utils/chain/chain-wallets/dfinity/post-message-transport-hook.ts +++ b/apps/wallet/src/utils/chain/chain-wallets/dfinity/post-message-transport-hook.ts @@ -1,4 +1,4 @@ -import { useEffect, useRef } from "react" +import { useCallback, useEffect } from "react" import { Icrc25PermissionsResult, Icrc25RequestPermissionsRequest, Icrc25RequestPermissionsResult, Icrc25SupportedStandardsResult, Icrc27AccountsResult, Icrc29StatusResult, Icrc32SignChallengeRequest, Icrc32SignChallengeResult, Icrc49CallCanisterRequest, IcrcErrorCode, IcrcErrorCodeMessages, IcrcMethods, IcrcPermissionState, JsonRpcRequest } from "./types" import { buildJsonRpcError, buildJsonRpcResponse, getIcrc29Session, NEED_PERMISSION_METHODS, parseJsonRpcRequest, setIcrc29Session, SUPPORTED_STANDARDS } from "./utils" import hibitIdSession from "../../../../stores/session" @@ -10,7 +10,7 @@ import { RuntimeEnv } from "../../../basicEnums" const ICRC_CHAIN_ID = Dfinity.chainId export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { - const handleMessageRef = useRef<(event: MessageEvent) => Promise>(async (event) => { + const handleMessage = useCallback(async (event: MessageEvent) => { let request: JsonRpcRequest | null = null try { request = parseJsonRpcRequest(event.data) @@ -25,9 +25,9 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { console.debug('ICRC29 not ready yet, ignored') return } - window.postMessage( + event.source?.postMessage( buildJsonRpcResponse(request.id, 'ready' as Icrc29StatusResult), - event.origin, + { targetOrigin: event.origin }, ) setIcrc29Session(event.origin, {}) return @@ -47,7 +47,7 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { currentPermissions[scope.method] = IcrcPermissionState.GRANTED } }) - window.postMessage( + event.source?.postMessage( buildJsonRpcResponse(request.id, { scopes: Object.keys(currentPermissions).map((method) => ({ scope: { @@ -56,7 +56,7 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { state: currentPermissions[method as IcrcMethods] ?? IcrcPermissionState.DENIED, })) }), - event.origin, + { targetOrigin: event.origin }, ) setIcrc29Session(event.origin, currentPermissions) return @@ -64,7 +64,7 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { if (request.method === IcrcMethods.ICRC25_PERMISSIONS) { const currentPermissions = { ...session.permissions } - window.postMessage( + event.source?.postMessage( buildJsonRpcResponse(request.id, { scopes: Object.keys(currentPermissions).map((method) => ({ scope: { @@ -73,32 +73,32 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { state: currentPermissions[method as IcrcMethods] ?? IcrcPermissionState.DENIED, })) }), - event.origin, + { targetOrigin: event.origin }, ) return } if (request.method === IcrcMethods.ICRC25_SUPPORTED_STANDARDS) { - window.postMessage( + event.source?.postMessage( buildJsonRpcResponse(request.id, { supportedStandards: SUPPORTED_STANDARDS }), - event.origin, + { targetOrigin: event.origin }, ) return } if (request.method === IcrcMethods.ICRC27_ACCOUNTS) { if (!hibitIdSession.walletPool || session.permissions[IcrcMethods.ICRC27_ACCOUNTS] !== IcrcPermissionState.GRANTED) { - window.postMessage( + event.source?.postMessage( buildJsonRpcError(request.id, IcrcErrorCode.PermissionNotGranted, IcrcErrorCodeMessages[IcrcErrorCode.PermissionNotGranted]), - event.origin, + { targetOrigin: event.origin }, ) return } try { const account = await hibitIdSession.walletPool.getAccount(ICRC_CHAIN_ID) - window.postMessage( + event.source?.postMessage( buildJsonRpcResponse(request.id, { accounts: [ { @@ -106,17 +106,17 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { } ], }), - event.origin, + { targetOrigin: event.origin }, ) } catch (e: any) { - window.postMessage( + event.source?.postMessage( buildJsonRpcError( request.id, IcrcErrorCode.GenericError, IcrcErrorCodeMessages[IcrcErrorCode.GenericError], e.message ?? JSON.stringify(e), ), - event.origin, + { targetOrigin: event.origin }, ) } return @@ -124,9 +124,9 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { if (request.method === IcrcMethods.ICRC32_SIGN_CHALLENGE) { if (!hibitIdSession.walletPool || session.permissions[IcrcMethods.ICRC32_SIGN_CHALLENGE] !== IcrcPermissionState.GRANTED) { - window.postMessage( + event.source?.postMessage( buildJsonRpcError(request.id, IcrcErrorCode.PermissionNotGranted, IcrcErrorCodeMessages[IcrcErrorCode.PermissionNotGranted]), - event.origin, + { targetOrigin: event.origin }, ) return } @@ -134,29 +134,29 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { const account = await hibitIdSession.walletPool.getAccount(ICRC_CHAIN_ID) const req = request as Icrc32SignChallengeRequest if (account.address !== req.params.principal) { - window.postMessage( + event.source?.postMessage( buildJsonRpcError(request.id, IcrcErrorCode.GenericError, IcrcErrorCodeMessages[IcrcErrorCode.GenericError], 'Principal does not match account'), - event.origin, + { targetOrigin: event.origin }, ) return } const signature = await hibitIdSession.walletPool.signMessage(req.params.challenge, ICRC_CHAIN_ID) - window.postMessage( + event.source?.postMessage( buildJsonRpcResponse(request.id, { publicKey: account.publicKey!, signature, }), - event.origin, + { targetOrigin: event.origin }, ) } catch (e: any) { - window.postMessage( + event.source?.postMessage( buildJsonRpcError( request.id, IcrcErrorCode.GenericError, IcrcErrorCodeMessages[IcrcErrorCode.GenericError], e.message ?? JSON.stringify(e), ), - event.origin, + { targetOrigin: event.origin }, ) } return @@ -164,9 +164,9 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { if (request.method === IcrcMethods.ICRC49_CALL_CANISTER) { if (!hibitIdSession.walletPool || session.permissions[IcrcMethods.ICRC49_CALL_CANISTER] !== IcrcPermissionState.GRANTED) { - window.postMessage( + event.source?.postMessage( buildJsonRpcError(request.id, IcrcErrorCode.PermissionNotGranted, IcrcErrorCodeMessages[IcrcErrorCode.PermissionNotGranted]), - event.origin, + { targetOrigin: event.origin }, ) return } @@ -174,30 +174,29 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { const wallet = hibitIdSession.walletPool.get(ICRC_CHAIN_ID) as DfinityChainWallet const req = request as Icrc49CallCanisterRequest const res = await wallet.Icrc49CallCanister(req) - window.postMessage(res, event.origin) + event.source?.postMessage(res, { targetOrigin: event.origin }) } catch (e: any) { - window.postMessage( + event.source?.postMessage( buildJsonRpcError( request.id, IcrcErrorCode.GenericError, IcrcErrorCodeMessages[IcrcErrorCode.GenericError], e.message ?? JSON.stringify(e), ), - event.origin, + { targetOrigin: event.origin }, ) } return } - }) + }, [isReady, hibitIdSession.walletPool]) useEffect(() => { if (RUNTIME_ENV !== RuntimeEnv.ICRC_POSTMESSAGE) { return } - const handleMessage = handleMessageRef.current window.addEventListener("message", handleMessage) return () => { window.removeEventListener("message", handleMessage) } - }, []) + }, [handleMessage]) } diff --git a/apps/wallet/src/utils/chain/index.ts b/apps/wallet/src/utils/chain/index.ts index 1164286..8e5292c 100644 --- a/apps/wallet/src/utils/chain/index.ts +++ b/apps/wallet/src/utils/chain/index.ts @@ -30,6 +30,7 @@ const SupportedChainsForTestnet = [ TonTestnet, // TronNile, // TODO: Dfinity testnet + Dfinity, ]; export function getChainByChainId(chainId: ChainId | null, devMode?: boolean): ChainInfo | null { From f0449d60f165bf0db9fcc211f6acb382e728fa36 Mon Sep 17 00:00:00 2001 From: Rustin Date: Sat, 28 Sep 2024 17:33:15 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=90=9B=20fix:=20icrc=20hook=20walletP?= =?UTF-8?q?ool=20await?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dfinity/post-message-transport-hook.ts | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/apps/wallet/src/utils/chain/chain-wallets/dfinity/post-message-transport-hook.ts b/apps/wallet/src/utils/chain/chain-wallets/dfinity/post-message-transport-hook.ts index 14acf90..2233dd0 100644 --- a/apps/wallet/src/utils/chain/chain-wallets/dfinity/post-message-transport-hook.ts +++ b/apps/wallet/src/utils/chain/chain-wallets/dfinity/post-message-transport-hook.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect } from "react" +import { useCallback, useEffect, useRef } from "react" import { Icrc25PermissionsResult, Icrc25RequestPermissionsRequest, Icrc25RequestPermissionsResult, Icrc25SupportedStandardsResult, Icrc27AccountsResult, Icrc29StatusResult, Icrc32SignChallengeRequest, Icrc32SignChallengeResult, Icrc49CallCanisterRequest, IcrcErrorCode, IcrcErrorCodeMessages, IcrcMethods, IcrcPermissionState, JsonRpcRequest } from "./types" import { buildJsonRpcError, buildJsonRpcResponse, getIcrc29Session, NEED_PERMISSION_METHODS, parseJsonRpcRequest, setIcrc29Session, SUPPORTED_STANDARDS } from "./utils" import hibitIdSession from "../../../../stores/session" @@ -6,10 +6,14 @@ import { Dfinity } from "../../chain-list" import { DfinityChainWallet } from "." import { RUNTIME_ENV } from "../../../runtime" import { RuntimeEnv } from "../../../basicEnums" +import { BridgePromise } from "@delandlabs/hibit-id-sdk" +import { ChainWalletPool } from ".." const ICRC_CHAIN_ID = Dfinity.chainId export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { + const walletPoolRef = useRef>(new BridgePromise()) + const handleMessage = useCallback(async (event: MessageEvent) => { let request: JsonRpcRequest | null = null try { @@ -89,7 +93,7 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { } if (request.method === IcrcMethods.ICRC27_ACCOUNTS) { - if (!hibitIdSession.walletPool || session.permissions[IcrcMethods.ICRC27_ACCOUNTS] !== IcrcPermissionState.GRANTED) { + if (session.permissions[IcrcMethods.ICRC27_ACCOUNTS] !== IcrcPermissionState.GRANTED) { event.source?.postMessage( buildJsonRpcError(request.id, IcrcErrorCode.PermissionNotGranted, IcrcErrorCodeMessages[IcrcErrorCode.PermissionNotGranted]), { targetOrigin: event.origin }, @@ -97,7 +101,8 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { return } try { - const account = await hibitIdSession.walletPool.getAccount(ICRC_CHAIN_ID) + const walletPool = await walletPoolRef.current.promise + const account = await walletPool.getAccount(ICRC_CHAIN_ID) event.source?.postMessage( buildJsonRpcResponse(request.id, { accounts: [ @@ -123,7 +128,7 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { } if (request.method === IcrcMethods.ICRC32_SIGN_CHALLENGE) { - if (!hibitIdSession.walletPool || session.permissions[IcrcMethods.ICRC32_SIGN_CHALLENGE] !== IcrcPermissionState.GRANTED) { + if (session.permissions[IcrcMethods.ICRC32_SIGN_CHALLENGE] !== IcrcPermissionState.GRANTED) { event.source?.postMessage( buildJsonRpcError(request.id, IcrcErrorCode.PermissionNotGranted, IcrcErrorCodeMessages[IcrcErrorCode.PermissionNotGranted]), { targetOrigin: event.origin }, @@ -131,7 +136,8 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { return } try { - const account = await hibitIdSession.walletPool.getAccount(ICRC_CHAIN_ID) + const walletPool = await walletPoolRef.current.promise + const account = await walletPool.getAccount(ICRC_CHAIN_ID) const req = request as Icrc32SignChallengeRequest if (account.address !== req.params.principal) { event.source?.postMessage( @@ -140,7 +146,7 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { ) return } - const signature = await hibitIdSession.walletPool.signMessage(req.params.challenge, ICRC_CHAIN_ID) + const signature = await walletPool.signMessage(req.params.challenge, ICRC_CHAIN_ID) event.source?.postMessage( buildJsonRpcResponse(request.id, { publicKey: account.publicKey!, @@ -163,7 +169,7 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { } if (request.method === IcrcMethods.ICRC49_CALL_CANISTER) { - if (!hibitIdSession.walletPool || session.permissions[IcrcMethods.ICRC49_CALL_CANISTER] !== IcrcPermissionState.GRANTED) { + if (session.permissions[IcrcMethods.ICRC49_CALL_CANISTER] !== IcrcPermissionState.GRANTED) { event.source?.postMessage( buildJsonRpcError(request.id, IcrcErrorCode.PermissionNotGranted, IcrcErrorCodeMessages[IcrcErrorCode.PermissionNotGranted]), { targetOrigin: event.origin }, @@ -171,7 +177,8 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { return } try { - const wallet = hibitIdSession.walletPool.get(ICRC_CHAIN_ID) as DfinityChainWallet + const walletPool = await walletPoolRef.current.promise + const wallet = walletPool.get(ICRC_CHAIN_ID) as DfinityChainWallet const req = request as Icrc49CallCanisterRequest const res = await wallet.Icrc49CallCanister(req) event.source?.postMessage(res, { targetOrigin: event.origin }) @@ -188,7 +195,13 @@ export const useDfinityIcrcPostMessageTransport = (isReady: boolean) => { } return } - }, [isReady, hibitIdSession.walletPool]) + }, [isReady]) + + useEffect(() => { + if (hibitIdSession.walletPool) { + walletPoolRef.current.resolve(hibitIdSession.walletPool) + } + }, [hibitIdSession.walletPool]) useEffect(() => { if (RUNTIME_ENV !== RuntimeEnv.ICRC_POSTMESSAGE) { From 09c4707d7ef9e6c6846941938551636a979642e7 Mon Sep 17 00:00:00 2001 From: Rustin Date: Sun, 29 Sep 2024 11:03:50 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=90=9B=20fix:=20icrc=20runtimes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wallet/package.json | 1 + .../chain/chain-wallets/dfinity/index.ts | 9 +++++---- apps/wallet/src/utils/runtime.ts | 19 +++++++++++++++++++ yarn.lock | 5 +++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/apps/wallet/package.json b/apps/wallet/package.json index e31315e..e56648b 100644 --- a/apps/wallet/package.json +++ b/apps/wallet/package.json @@ -36,6 +36,7 @@ "ahooks": "^3.8.0", "borc": "^3.0.0", "buffer": "^6.0.3", + "cborg": "^4.2.4", "class-transformer": "^0.5.1", "dayjs": "^1.11.11", "ethers": "^6.13.1", diff --git a/apps/wallet/src/utils/chain/chain-wallets/dfinity/index.ts b/apps/wallet/src/utils/chain/chain-wallets/dfinity/index.ts index 4929e33..3d911ba 100644 --- a/apps/wallet/src/utils/chain/chain-wallets/dfinity/index.ts +++ b/apps/wallet/src/utils/chain/chain-wallets/dfinity/index.ts @@ -11,8 +11,8 @@ import { IcrcLedgerCanister } from "@dfinity/ledger-icrc"; import { Principal } from "@dfinity/principal"; import { Icrc49CallCanisterRequest, Icrc49CallCanisterResult, IcrcErrorCode, JsonRpcResponseError, JsonRpcResponseSuccess } from "./types"; import { buildJsonRpcError, buildJsonRpcResponse } from "./utils"; -// @ts-ignore -import cbor from 'borc'; +import * as cbor from 'cborg'; +import { RUNTIME_ICRC_DEV, RUNTIME_ICRC_HOST } from "../../../runtime"; const ICP_LEDGER_CANISTER_ID = Principal.fromText('ryjl3-tyaaa-aaaaa-aaaba-cai'); @@ -148,7 +148,7 @@ export class DfinityChainWallet extends BaseChainWallet { } ) return buildJsonRpcResponse(request.id, { - contentMap: cbor.encode(response.requestDetails), + contentMap: Buffer.from(cbor.encode(response.requestDetails)).toString('base64'), certificate: Buffer.from(response.response.body?.certificate!).toString('base64'), }) } catch (e: any) { @@ -160,7 +160,8 @@ export class DfinityChainWallet extends BaseChainWallet { this.identity = Secp256k1KeyIdentity.fromSeedPhrase(phrase) this.agent = await createAgent({ identity: this.identity, - host: 'https://ic0.app', + host: RUNTIME_ICRC_HOST || 'https://ic0.app', + fetchRootKey: RUNTIME_ICRC_DEV, }) } diff --git a/apps/wallet/src/utils/runtime.ts b/apps/wallet/src/utils/runtime.ts index 87c1b6e..c8236e3 100644 --- a/apps/wallet/src/utils/runtime.ts +++ b/apps/wallet/src/utils/runtime.ts @@ -7,6 +7,8 @@ import { Dfinity } from "./chain/chain-list"; export const IS_IN_IFRAME = window.top !== window.self; let runtimeEnv: RuntimeEnv = RuntimeEnv.SDK; +let runtimeIcrcHost: string | undefined = undefined; +let runtimeIcrcDev: boolean = false; let runtimeParamsRaw: string | undefined = undefined; let runtimeParams: unknown = undefined; let runtimeSupportedChainIds: ChainId[] = []; @@ -28,10 +30,23 @@ try { } } catch (e) { /* empty */ } +// Dfinity ICRC PostMessage if (urlParams.has('is_icrc') || sessionStorage.getItem('is_icrc')) { runtimeEnv = RuntimeEnv.ICRC_POSTMESSAGE runtimeSupportedChainIds = [Dfinity.chainId] sessionStorage.setItem('is_icrc', '1') + if (urlParams.get('icrc_host') || sessionStorage.getItem('icrc_host')) { + runtimeIcrcHost = urlParams.get('icrc_host') || sessionStorage.getItem('icrc_host') || undefined + if (runtimeIcrcHost) { + sessionStorage.setItem('icrc_host', runtimeIcrcHost) + } + } + if (urlParams.get('icrc_dev') || sessionStorage.getItem('icrc_dev')) { + runtimeIcrcDev = !!(urlParams.get('icrc_dev') || sessionStorage.getItem('icrc_dev')) + if (runtimeIcrcDev) { + sessionStorage.setItem('icrc_dev', '1') + } + } } urlParams.get('chains')?.split(',').forEach((idStr) => { @@ -44,12 +59,16 @@ runtimeLang = urlParams.get('lang') as Language || undefined export const IS_TELEGRAM_MINI_APP = isTelegramMiniApp; export const RUNTIME_ENV = runtimeEnv +export const RUNTIME_ICRC_HOST = runtimeIcrcHost +export const RUNTIME_ICRC_DEV = runtimeIcrcDev export const RUNTIME_PARAMS_RAW = runtimeParamsRaw export const RUNTIME_PARAMS = runtimeParams export const RUNTIME_SUPPORTED_CHAIN_IDS = runtimeSupportedChainIds export const RUNTIME_LANG = runtimeLang console.debug('[runtime env]', RUNTIME_ENV) +console.debug('[runtime icrc host]', RUNTIME_ICRC_HOST) +console.debug('[runtime icrc dev]', RUNTIME_ICRC_DEV) console.debug('[runtime params]', RUNTIME_PARAMS) console.debug('[runtime supported chains]', RUNTIME_SUPPORTED_CHAIN_IDS) console.debug('[runtime lang]', RUNTIME_LANG) diff --git a/yarn.lock b/yarn.lock index c4af442..b0548a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1904,6 +1904,11 @@ caniuse-lite@^1.0.30001646: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001659.tgz#f370c311ffbc19c4965d8ec0064a3625c8aaa7af" integrity sha512-Qxxyfv3RdHAfJcXelgf0hU4DFUVXBGTjqrBUZLUh8AtlGnsDo+CnncYtTd95+ZKfnANUOzxyIQCuU/UeBZBYoA== +cborg@^4.2.4: + version "4.2.4" + resolved "https://registry.npmmirror.com/cborg/-/cborg-4.2.4.tgz#33f5c18bda7cae33fb0c7e84d329bce2e51e1789" + integrity sha512-ns2xY95zViHIVy4lq+qdLmfXTpnT3XjmKradz4RJxxbr5jc/A5gS5FiFLcPGhSdHVlSeeoizT1fuKdI1Kcd6oA== + chai@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.1.tgz#f035d9792a22b481ead1c65908d14bb62ec1c82c" From 02f02934a16d1096c083928ded90f3c84082892a Mon Sep 17 00:00:00 2001 From: Rustin Date: Sun, 29 Sep 2024 17:08:03 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=90=9B=20fix:=20icrc49=20http=20statu?= =?UTF-8?q?s=20handling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wallet/src/utils/chain/chain-wallets/dfinity/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/wallet/src/utils/chain/chain-wallets/dfinity/index.ts b/apps/wallet/src/utils/chain/chain-wallets/dfinity/index.ts index 3d911ba..ae7a6b9 100644 --- a/apps/wallet/src/utils/chain/chain-wallets/dfinity/index.ts +++ b/apps/wallet/src/utils/chain/chain-wallets/dfinity/index.ts @@ -147,6 +147,9 @@ export class DfinityChainWallet extends BaseChainWallet { callSync: true, } ) + if (response.response.status > 202) { + throw new Error(`ICRC49 call failed with http status ${response.response.status}`) + } return buildJsonRpcResponse(request.id, { contentMap: Buffer.from(cbor.encode(response.requestDetails)).toString('base64'), certificate: Buffer.from(response.response.body?.certificate!).toString('base64'),