eth-twc-sdk-react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +279 -0
- package/hooks/clients.ts +12 -0
- package/hooks/configInfo.ts +33 -0
- package/hooks/index.ts +36 -0
- package/hooks/sdkConfig.ts +7 -0
- package/hooks/selfTransfer.ts +83 -0
- package/hooks/sign.ts +133 -0
- package/hooks/signatureTransfer.ts +110 -0
- package/hooks/verify.ts +67 -0
- package/index.ts +1 -0
- package/package.json +40 -0
- package/test/clients.test.ts +33 -0
- package/test/fixtures.ts +11 -0
- package/test/hooks.configInfo.test.ts +94 -0
- package/test/hooks.selfTransfer.test.ts +173 -0
- package/test/hooks.sign.test.ts +231 -0
- package/test/hooks.signatureTransfer.test.ts +198 -0
- package/test/hooks.verify.test.ts +230 -0
- package/test/preload.ts +81 -0
- package/test/queryClient.tsx +17 -0
- package/test/sdkConfigState.ts +33 -0
- package/test/stubs.ts +257 -0
- package/test/tsconfig.json +8 -0
- package/test/wagmiState.ts +18 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useMutation, type UseMutationOptions } from "@tanstack/react-query";
|
|
4
|
+
import type { SignedBatchTransfer } from "eth-twc-sdk-js/signatureTransfer/batch";
|
|
5
|
+
import type { SignedCancelAuthorization } from "eth-twc-sdk-js/signatureTransfer/cancelAuthorization";
|
|
6
|
+
import type { SignedSingleTransfer } from "eth-twc-sdk-js/signatureTransfer/single";
|
|
7
|
+
import type { SignedUnifiedTransfer } from "eth-twc-sdk-js/signatureTransfer/unified";
|
|
8
|
+
import { sendTx as sendAuthorizedBatch } from "eth-twc-sdk-js/signatureTransfer/batch";
|
|
9
|
+
import { sendTx as sendCancelAuthorization } from "eth-twc-sdk-js/signatureTransfer/cancelAuthorization";
|
|
10
|
+
import { sendTx as sendAuthorizedSingle } from "eth-twc-sdk-js/signatureTransfer/single";
|
|
11
|
+
import { sendTx as sendAuthorizedUnified } from "eth-twc-sdk-js/signatureTransfer/unified";
|
|
12
|
+
import type { Hex } from "viem";
|
|
13
|
+
import { useConnection, usePublicClient, useWalletClient } from "wagmi";
|
|
14
|
+
|
|
15
|
+
import { narrowWriteClients } from "./clients.ts";
|
|
16
|
+
|
|
17
|
+
export function useSendAuthorizedSingleTransfer(
|
|
18
|
+
options?: Omit<
|
|
19
|
+
UseMutationOptions<Hex, Error, SignedSingleTransfer>,
|
|
20
|
+
"mutationFn"
|
|
21
|
+
>,
|
|
22
|
+
) {
|
|
23
|
+
const publicClient = usePublicClient();
|
|
24
|
+
const { data: walletClient } = useWalletClient();
|
|
25
|
+
const { address } = useConnection();
|
|
26
|
+
|
|
27
|
+
return useMutation({
|
|
28
|
+
...options,
|
|
29
|
+
mutationFn: async (signed: SignedSingleTransfer) => {
|
|
30
|
+
const [pc, wc, addr] = narrowWriteClients(
|
|
31
|
+
publicClient,
|
|
32
|
+
walletClient,
|
|
33
|
+
address,
|
|
34
|
+
);
|
|
35
|
+
return sendAuthorizedSingle(pc, wc, addr, signed);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function useSendAuthorizedUnifiedTransfer(
|
|
41
|
+
options?: Omit<
|
|
42
|
+
UseMutationOptions<Hex, Error, SignedUnifiedTransfer>,
|
|
43
|
+
"mutationFn"
|
|
44
|
+
>,
|
|
45
|
+
) {
|
|
46
|
+
const publicClient = usePublicClient();
|
|
47
|
+
const { data: walletClient } = useWalletClient();
|
|
48
|
+
const { address } = useConnection();
|
|
49
|
+
|
|
50
|
+
return useMutation({
|
|
51
|
+
...options,
|
|
52
|
+
mutationFn: async (signed: SignedUnifiedTransfer) => {
|
|
53
|
+
const [pc, wc, addr] = narrowWriteClients(
|
|
54
|
+
publicClient,
|
|
55
|
+
walletClient,
|
|
56
|
+
address,
|
|
57
|
+
);
|
|
58
|
+
return sendAuthorizedUnified(pc, wc, addr, signed);
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const useSendAuthorizedUniCommitTransfers =
|
|
64
|
+
useSendAuthorizedUnifiedTransfer;
|
|
65
|
+
|
|
66
|
+
export function useSendAuthorizedBatchTransfer(
|
|
67
|
+
options?: Omit<
|
|
68
|
+
UseMutationOptions<Hex, Error, SignedBatchTransfer>,
|
|
69
|
+
"mutationFn"
|
|
70
|
+
>,
|
|
71
|
+
) {
|
|
72
|
+
const publicClient = usePublicClient();
|
|
73
|
+
const { data: walletClient } = useWalletClient();
|
|
74
|
+
const { address } = useConnection();
|
|
75
|
+
|
|
76
|
+
return useMutation({
|
|
77
|
+
...options,
|
|
78
|
+
mutationFn: async (signed: SignedBatchTransfer) => {
|
|
79
|
+
const [pc, wc, addr] = narrowWriteClients(
|
|
80
|
+
publicClient,
|
|
81
|
+
walletClient,
|
|
82
|
+
address,
|
|
83
|
+
);
|
|
84
|
+
return sendAuthorizedBatch(pc, wc, addr, signed);
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function useSendCancelAuthorization(
|
|
90
|
+
options?: Omit<
|
|
91
|
+
UseMutationOptions<Hex, Error, SignedCancelAuthorization>,
|
|
92
|
+
"mutationFn"
|
|
93
|
+
>,
|
|
94
|
+
) {
|
|
95
|
+
const publicClient = usePublicClient();
|
|
96
|
+
const { data: walletClient } = useWalletClient();
|
|
97
|
+
const { address } = useConnection();
|
|
98
|
+
|
|
99
|
+
return useMutation({
|
|
100
|
+
...options,
|
|
101
|
+
mutationFn: async (signed: SignedCancelAuthorization) => {
|
|
102
|
+
const [pc, wc, addr] = narrowWriteClients(
|
|
103
|
+
publicClient,
|
|
104
|
+
walletClient,
|
|
105
|
+
address,
|
|
106
|
+
);
|
|
107
|
+
return sendCancelAuthorization(pc, wc, addr, signed);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
package/hooks/verify.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
useQuery,
|
|
5
|
+
type UseQueryOptions,
|
|
6
|
+
type UseQueryResult,
|
|
7
|
+
} from "@tanstack/react-query";
|
|
8
|
+
import {
|
|
9
|
+
getTransferWithCommitmentSentEventLogs,
|
|
10
|
+
verify,
|
|
11
|
+
} from "eth-twc-sdk-js/verify";
|
|
12
|
+
import type { Hex, Log } from "viem";
|
|
13
|
+
import { usePublicClient } from "wagmi";
|
|
14
|
+
|
|
15
|
+
/** Args for `verify` — same shape as the third argument to `eth-twc-sdk-js/verify`. */
|
|
16
|
+
export type VerifyTransferArgs = Parameters<typeof verify>[2];
|
|
17
|
+
|
|
18
|
+
export function useVerifyTransfer(
|
|
19
|
+
txHash: Hex | undefined,
|
|
20
|
+
args: VerifyTransferArgs | undefined,
|
|
21
|
+
options?: Omit<UseQueryOptions<null, Error, null>, "queryKey" | "queryFn">,
|
|
22
|
+
): UseQueryResult<null, Error> {
|
|
23
|
+
const publicClient = usePublicClient();
|
|
24
|
+
const { enabled: enabledOption, ...queryOptions } = options ?? {};
|
|
25
|
+
|
|
26
|
+
return useQuery({
|
|
27
|
+
...queryOptions,
|
|
28
|
+
queryKey: [
|
|
29
|
+
"twc",
|
|
30
|
+
"verify",
|
|
31
|
+
txHash ?? null,
|
|
32
|
+
args?.from ?? null,
|
|
33
|
+
args?.token ?? null,
|
|
34
|
+
args?.to ?? null,
|
|
35
|
+
args != null ? args.value.toString() : null,
|
|
36
|
+
args?.commitment ?? null,
|
|
37
|
+
],
|
|
38
|
+
queryFn: async () => {
|
|
39
|
+
if (!publicClient) throw new Error("TWC: public client is not available");
|
|
40
|
+
if (!txHash) throw new Error("TWC: tx hash is required");
|
|
41
|
+
if (!args) throw new Error("TWC: verify args are required");
|
|
42
|
+
await verify(publicClient, txHash, args);
|
|
43
|
+
return null;
|
|
44
|
+
},
|
|
45
|
+
enabled:
|
|
46
|
+
Boolean(publicClient && txHash && args) && (enabledOption ?? true),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function useTransferWithCommitmentSentLogs(
|
|
51
|
+
txHash: Hex | undefined,
|
|
52
|
+
options?: Omit<UseQueryOptions<Log[], Error, Log[]>, "queryKey" | "queryFn">,
|
|
53
|
+
): UseQueryResult<Log[], Error> {
|
|
54
|
+
const publicClient = usePublicClient();
|
|
55
|
+
const { enabled: enabledOption, ...queryOptions } = options ?? {};
|
|
56
|
+
|
|
57
|
+
return useQuery({
|
|
58
|
+
...queryOptions,
|
|
59
|
+
queryKey: ["twc", "transferWithCommitmentSent", txHash ?? null],
|
|
60
|
+
queryFn: async () => {
|
|
61
|
+
if (!publicClient) throw new Error("TWC: public client is not available");
|
|
62
|
+
if (!txHash) throw new Error("TWC: tx hash is required");
|
|
63
|
+
return getTransferWithCommitmentSentEventLogs(publicClient, txHash);
|
|
64
|
+
},
|
|
65
|
+
enabled: Boolean(publicClient && txHash) && (enabledOption ?? true),
|
|
66
|
+
});
|
|
67
|
+
}
|
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./hooks/index.ts";
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eth-twc-sdk-react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"module": "index.ts",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./index.ts"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "bun test --preload ./test/preload.ts --concurrency 1 ./test/",
|
|
11
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p test/tsconfig.json"
|
|
12
|
+
},
|
|
13
|
+
"peerDependencies": {
|
|
14
|
+
"@tanstack/react-query": "^5.59.0",
|
|
15
|
+
"react": "^18 || ^19",
|
|
16
|
+
"typescript": "^5",
|
|
17
|
+
"viem": "^2.0.0",
|
|
18
|
+
"wagmi": "^3.0.0"
|
|
19
|
+
},
|
|
20
|
+
"peerDependenciesMeta": {
|
|
21
|
+
"typescript": {
|
|
22
|
+
"optional": true
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"eth-twc-sdk-js": "^0.1.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@tanstack/react-query": "^5.99.0",
|
|
30
|
+
"@testing-library/react": "^16.3.0",
|
|
31
|
+
"@types/bun": "latest",
|
|
32
|
+
"@types/react": "^19",
|
|
33
|
+
"happy-dom": "^20.0.10",
|
|
34
|
+
"react": "^19.2.5",
|
|
35
|
+
"react-dom": "^19.2.5",
|
|
36
|
+
"typescript": "^5",
|
|
37
|
+
"viem": "2.x",
|
|
38
|
+
"wagmi": "^3.6.1"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { mainnet } from "viem/chains";
|
|
3
|
+
import type { Hex, PublicClient, WalletClient } from "viem";
|
|
4
|
+
|
|
5
|
+
import { narrowWriteClients } from "../hooks/clients.ts";
|
|
6
|
+
|
|
7
|
+
describe("narrowWriteClients", () => {
|
|
8
|
+
const pc = { chain: mainnet } as unknown as PublicClient;
|
|
9
|
+
const wc = { chain: mainnet } as unknown as WalletClient;
|
|
10
|
+
const addr = "0x1111111111111111111111111111111111111111" as Hex;
|
|
11
|
+
|
|
12
|
+
test("public client が無いときは TWC: public client", () => {
|
|
13
|
+
expect(() =>
|
|
14
|
+
narrowWriteClients(undefined, wc, addr),
|
|
15
|
+
).toThrow(/TWC: public client is not available/);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("wallet client が無いときは TWC: wallet client", () => {
|
|
19
|
+
expect(() => narrowWriteClients(pc, undefined, addr)).toThrow(
|
|
20
|
+
/TWC: wallet client is not available/,
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("address が無いときは connect a wallet", () => {
|
|
25
|
+
expect(() => narrowWriteClients(pc, wc, undefined)).toThrow(
|
|
26
|
+
/TWC: connect a wallet to send or sign/,
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("揃っているときはタプルを返す", () => {
|
|
31
|
+
expect(narrowWriteClients(pc, wc, addr)).toEqual([pc, wc, addr]);
|
|
32
|
+
});
|
|
33
|
+
});
|
package/test/fixtures.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { renderHook, waitFor } from "@testing-library/react";
|
|
2
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
3
|
+
import type { Chain, PublicClient } from "viem";
|
|
4
|
+
import { mainnet } from "viem/chains";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
useIsSupportedChain,
|
|
8
|
+
useIsTransferWithCommitmentDeployed,
|
|
9
|
+
} from "../hooks/configInfo.ts";
|
|
10
|
+
import { EIP712_DOMAIN_NAME } from "../hooks/sdkConfig.ts";
|
|
11
|
+
import { TEST_VERIFIER_CONTRACT } from "./fixtures.ts";
|
|
12
|
+
import { createQueryWrapper, createTestQueryClient } from "./queryClient.tsx";
|
|
13
|
+
import { resetSdkConfigAddress, sdkConfigState } from "./sdkConfigState.ts";
|
|
14
|
+
import { resetWagmiState, wagmiState } from "./wagmiState.ts";
|
|
15
|
+
import { stubPublicClient } from "./stubs.ts";
|
|
16
|
+
|
|
17
|
+
describe("sdkConfig 再エクスポート", () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
resetSdkConfigAddress();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("transferWithCommitmentAddress はモック config と一致", () => {
|
|
23
|
+
expect(sdkConfigState.transferWithCommitmentAddress).toBe(
|
|
24
|
+
TEST_VERIFIER_CONTRACT,
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("EIP712_DOMAIN_NAME がコントラクトと一致", () => {
|
|
29
|
+
expect(EIP712_DOMAIN_NAME).toBe("TransferWithCommitment");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe("useIsTransferWithCommitmentDeployed", () => {
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
resetWagmiState();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("public client が無いときは false", () => {
|
|
39
|
+
const qc = createTestQueryClient();
|
|
40
|
+
const { result } = renderHook(() => useIsTransferWithCommitmentDeployed(), {
|
|
41
|
+
wrapper: createQueryWrapper(qc),
|
|
42
|
+
});
|
|
43
|
+
expect(result.current).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("getCode が空なら false", async () => {
|
|
47
|
+
const qc = createTestQueryClient();
|
|
48
|
+
wagmiState.publicClient = stubPublicClient({
|
|
49
|
+
getCode: mock(() => Promise.resolve("0x")) as unknown as PublicClient["getCode"],
|
|
50
|
+
});
|
|
51
|
+
const { result } = renderHook(() => useIsTransferWithCommitmentDeployed(), {
|
|
52
|
+
wrapper: createQueryWrapper(qc),
|
|
53
|
+
});
|
|
54
|
+
await waitFor(() => expect(result.current).toBe(false));
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("getCode が非空なら true", async () => {
|
|
58
|
+
const qc = createTestQueryClient();
|
|
59
|
+
wagmiState.publicClient = stubPublicClient({
|
|
60
|
+
chain: mainnet,
|
|
61
|
+
getCode: mock(() =>
|
|
62
|
+
Promise.resolve("0x6000"),
|
|
63
|
+
) as unknown as PublicClient["getCode"],
|
|
64
|
+
});
|
|
65
|
+
const { result } = renderHook(() => useIsTransferWithCommitmentDeployed(), {
|
|
66
|
+
wrapper: createQueryWrapper(qc),
|
|
67
|
+
});
|
|
68
|
+
await waitFor(() => expect(result.current).toBe(true));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("未知名義の chain でも getCode が成功すれば評価される", async () => {
|
|
72
|
+
const qc = createTestQueryClient();
|
|
73
|
+
wagmiState.publicClient = stubPublicClient({
|
|
74
|
+
chain: { id: 999_999, name: "Unknown" } as unknown as Chain,
|
|
75
|
+
getCode: mock(() =>
|
|
76
|
+
Promise.resolve("0x6000"),
|
|
77
|
+
) as unknown as PublicClient["getCode"],
|
|
78
|
+
});
|
|
79
|
+
const { result } = renderHook(() => useIsTransferWithCommitmentDeployed(), {
|
|
80
|
+
wrapper: createQueryWrapper(qc),
|
|
81
|
+
});
|
|
82
|
+
await waitFor(() => expect(result.current).toBe(true));
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe("useIsSupportedChain(非推奨エイリアス)", () => {
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
resetWagmiState();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("useIsTransferWithCommitmentDeployed と同じ参照", () => {
|
|
92
|
+
expect(useIsSupportedChain).toBe(useIsTransferWithCommitmentDeployed);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { renderHook, waitFor } from "@testing-library/react";
|
|
2
|
+
import { beforeEach, describe, expect, test } from "bun:test";
|
|
3
|
+
import type { Hex } from "viem";
|
|
4
|
+
import { mainnet } from "viem/chains";
|
|
5
|
+
|
|
6
|
+
import { useSelfBatchTransfer, useSelfTransfer, useSelfUnifiedTransfer } from "../hooks/selfTransfer.ts";
|
|
7
|
+
import { ADDR, ADDR_B, COMMIT } from "./fixtures.ts";
|
|
8
|
+
import { createQueryWrapper, createTestQueryClient } from "./queryClient.tsx";
|
|
9
|
+
import { resetSdkConfigAddress, setSdkConfigAddressZero } from "./sdkConfigState.ts";
|
|
10
|
+
import {
|
|
11
|
+
stubClientsSelfTransferSimulateRpcError,
|
|
12
|
+
stubClientsSelfTransferSuccess,
|
|
13
|
+
stubPublicClient,
|
|
14
|
+
stubWalletClient,
|
|
15
|
+
} from "./stubs.ts";
|
|
16
|
+
import { resetWagmiState, wagmiState } from "./wagmiState.ts";
|
|
17
|
+
|
|
18
|
+
describe("useSelfTransfer / useSelfUnifiedTransfer / useSelfBatchTransfer", () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
resetWagmiState();
|
|
21
|
+
resetSdkConfigAddress();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("未接続(address なし)は mutate が narrowWriteClients で失敗", async () => {
|
|
25
|
+
wagmiState.publicClient = stubPublicClient();
|
|
26
|
+
wagmiState.walletClient = stubWalletClient();
|
|
27
|
+
wagmiState.address = undefined;
|
|
28
|
+
|
|
29
|
+
const qc = createTestQueryClient();
|
|
30
|
+
const { result } = renderHook(() => useSelfTransfer(), {
|
|
31
|
+
wrapper: createQueryWrapper(qc),
|
|
32
|
+
});
|
|
33
|
+
result.current.mutate({
|
|
34
|
+
token: ADDR,
|
|
35
|
+
to: ADDR_B,
|
|
36
|
+
value: 1n,
|
|
37
|
+
commitment: COMMIT,
|
|
38
|
+
});
|
|
39
|
+
await waitFor(() => expect(result.current.isError).toBe(true));
|
|
40
|
+
expect(result.current.error?.message).toMatch(
|
|
41
|
+
/TWC: connect a wallet to send or sign/,
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("sdk_js: transferWithCommitmentAddress がゼロのとき assert が失敗", async () => {
|
|
46
|
+
setSdkConfigAddressZero();
|
|
47
|
+
const { publicClient: pc, walletClient } = stubClientsSelfTransferSuccess();
|
|
48
|
+
wagmiState.publicClient = stubPublicClient({
|
|
49
|
+
simulateContract: pc.simulateContract,
|
|
50
|
+
getCode: async () => "0x",
|
|
51
|
+
});
|
|
52
|
+
wagmiState.walletClient = walletClient;
|
|
53
|
+
wagmiState.address = ADDR as Hex;
|
|
54
|
+
|
|
55
|
+
const qc = createTestQueryClient();
|
|
56
|
+
const { result } = renderHook(() => useSelfTransfer(), {
|
|
57
|
+
wrapper: createQueryWrapper(qc),
|
|
58
|
+
});
|
|
59
|
+
result.current.mutate({
|
|
60
|
+
token: ADDR,
|
|
61
|
+
to: ADDR_B,
|
|
62
|
+
value: 1n,
|
|
63
|
+
commitment: COMMIT,
|
|
64
|
+
});
|
|
65
|
+
await waitFor(() => expect(result.current.isError).toBe(true));
|
|
66
|
+
expect(result.current.error?.message).toMatch(
|
|
67
|
+
/not deployed at/,
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("RPC: simulateContract が拒否されると mutation error にメッセージが伝播", async () => {
|
|
72
|
+
const { publicClient, walletClient } = stubClientsSelfTransferSimulateRpcError();
|
|
73
|
+
wagmiState.publicClient = publicClient;
|
|
74
|
+
wagmiState.walletClient = walletClient;
|
|
75
|
+
wagmiState.address = ADDR as Hex;
|
|
76
|
+
|
|
77
|
+
const qc = createTestQueryClient();
|
|
78
|
+
const { result } = renderHook(() => useSelfTransfer(), {
|
|
79
|
+
wrapper: createQueryWrapper(qc),
|
|
80
|
+
});
|
|
81
|
+
result.current.mutate({
|
|
82
|
+
token: ADDR,
|
|
83
|
+
to: ADDR_B,
|
|
84
|
+
value: 1n,
|
|
85
|
+
commitment: COMMIT,
|
|
86
|
+
});
|
|
87
|
+
await waitFor(() => expect(result.current.isError).toBe(true));
|
|
88
|
+
expect(result.current.error?.message).toMatch(/RPC: eth_call failed/);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("PublicClient と WalletClient の chain.id が異なれば chain mismatch", async () => {
|
|
92
|
+
const { publicClient, walletClient } = stubClientsSelfTransferSuccess();
|
|
93
|
+
wagmiState.publicClient = {
|
|
94
|
+
...publicClient,
|
|
95
|
+
chain: mainnet,
|
|
96
|
+
} as typeof publicClient;
|
|
97
|
+
wagmiState.walletClient = {
|
|
98
|
+
...walletClient,
|
|
99
|
+
chain: { id: 137, name: "Polygon" },
|
|
100
|
+
} as typeof walletClient;
|
|
101
|
+
wagmiState.address = ADDR as Hex;
|
|
102
|
+
|
|
103
|
+
const qc = createTestQueryClient();
|
|
104
|
+
const { result } = renderHook(() => useSelfTransfer(), {
|
|
105
|
+
wrapper: createQueryWrapper(qc),
|
|
106
|
+
});
|
|
107
|
+
result.current.mutate({
|
|
108
|
+
token: ADDR,
|
|
109
|
+
to: ADDR_B,
|
|
110
|
+
value: 1n,
|
|
111
|
+
commitment: COMMIT,
|
|
112
|
+
});
|
|
113
|
+
await waitFor(() => expect(result.current.isError).toBe(true));
|
|
114
|
+
expect(result.current.error?.message).toMatch(/chain mismatch/);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("成功時は write の戻り tx ハッシュが data になる", async () => {
|
|
118
|
+
const { publicClient, walletClient } = stubClientsSelfTransferSuccess();
|
|
119
|
+
wagmiState.publicClient = publicClient;
|
|
120
|
+
wagmiState.walletClient = walletClient;
|
|
121
|
+
wagmiState.address = ADDR as Hex;
|
|
122
|
+
|
|
123
|
+
const qc = createTestQueryClient();
|
|
124
|
+
const { result } = renderHook(() => useSelfTransfer(), {
|
|
125
|
+
wrapper: createQueryWrapper(qc),
|
|
126
|
+
});
|
|
127
|
+
result.current.mutate({
|
|
128
|
+
token: ADDR,
|
|
129
|
+
to: ADDR_B,
|
|
130
|
+
value: 1n,
|
|
131
|
+
commitment: COMMIT,
|
|
132
|
+
});
|
|
133
|
+
await waitFor(() => expect(result.current.isSuccess).toBe(true));
|
|
134
|
+
expect(result.current.data).toMatch(/^0x[a-fA-F0-9]+$/);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("useSelfUnifiedTransfer も同様に RPC 失敗を伝播", async () => {
|
|
138
|
+
const { publicClient, walletClient } = stubClientsSelfTransferSimulateRpcError();
|
|
139
|
+
wagmiState.publicClient = publicClient;
|
|
140
|
+
wagmiState.walletClient = walletClient;
|
|
141
|
+
wagmiState.address = ADDR as Hex;
|
|
142
|
+
|
|
143
|
+
const qc = createTestQueryClient();
|
|
144
|
+
const { result } = renderHook(() => useSelfUnifiedTransfer(), {
|
|
145
|
+
wrapper: createQueryWrapper(qc),
|
|
146
|
+
});
|
|
147
|
+
result.current.mutate({
|
|
148
|
+
details: [{ to: ADDR_B, token: ADDR, value: 1n }],
|
|
149
|
+
commitment: COMMIT,
|
|
150
|
+
});
|
|
151
|
+
await waitFor(() => expect(result.current.isError).toBe(true));
|
|
152
|
+
expect(result.current.error?.message).toMatch(/RPC: eth_call failed/);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("useSelfBatchTransfer も同様に RPC 失敗を伝播", async () => {
|
|
156
|
+
const { publicClient, walletClient } = stubClientsSelfTransferSimulateRpcError();
|
|
157
|
+
wagmiState.publicClient = publicClient;
|
|
158
|
+
wagmiState.walletClient = walletClient;
|
|
159
|
+
wagmiState.address = ADDR as Hex;
|
|
160
|
+
|
|
161
|
+
const qc = createTestQueryClient();
|
|
162
|
+
const { result } = renderHook(() => useSelfBatchTransfer(), {
|
|
163
|
+
wrapper: createQueryWrapper(qc),
|
|
164
|
+
});
|
|
165
|
+
result.current.mutate({
|
|
166
|
+
details: [
|
|
167
|
+
{ to: ADDR_B, token: ADDR, value: 1n, commitment: COMMIT },
|
|
168
|
+
],
|
|
169
|
+
});
|
|
170
|
+
await waitFor(() => expect(result.current.isError).toBe(true));
|
|
171
|
+
expect(result.current.error?.message).toMatch(/RPC: eth_call failed/);
|
|
172
|
+
});
|
|
173
|
+
});
|