@pay-skill/sdk 0.1.8 → 0.1.11
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 +80 -91
- package/dist/auth.d.ts +11 -6
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +19 -7
- package/dist/auth.js.map +1 -1
- package/dist/errors.d.ts +4 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +8 -3
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -6
- package/dist/index.js.map +1 -1
- package/dist/keychain.d.ts +8 -0
- package/dist/keychain.d.ts.map +1 -0
- package/dist/keychain.js +17 -0
- package/dist/keychain.js.map +1 -0
- package/dist/wallet.d.ts +136 -104
- package/dist/wallet.d.ts.map +1 -1
- package/dist/wallet.js +658 -275
- package/dist/wallet.js.map +1 -1
- package/jsr.json +1 -1
- package/package.json +5 -2
- package/src/auth.ts +28 -18
- package/src/errors.ts +10 -3
- package/src/index.ts +12 -39
- package/src/keychain.ts +18 -0
- package/src/wallet.ts +1054 -355
- package/tests/test_auth_rejection.ts +43 -95
- package/tests/test_crypto.ts +59 -172
- package/tests/test_e2e.ts +46 -105
- package/tests/test_errors.ts +9 -1
- package/tests/test_ows.ts +153 -0
- package/tests/test_wallet.ts +194 -0
- package/dist/client.d.ts +0 -94
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -443
- package/dist/client.js.map +0 -1
- package/dist/models.d.ts +0 -78
- package/dist/models.d.ts.map +0 -1
- package/dist/models.js +0 -2
- package/dist/models.js.map +0 -1
- package/dist/ows-signer.d.ts +0 -75
- package/dist/ows-signer.d.ts.map +0 -1
- package/dist/ows-signer.js +0 -130
- package/dist/ows-signer.js.map +0 -1
- package/dist/signer.d.ts +0 -46
- package/dist/signer.d.ts.map +0 -1
- package/dist/signer.js +0 -111
- package/dist/signer.js.map +0 -1
- package/src/client.ts +0 -644
- package/src/models.ts +0 -77
- package/src/ows-signer.ts +0 -223
- package/src/signer.ts +0 -147
- package/tests/test_ows_integration.ts +0 -92
- package/tests/test_ows_signer.ts +0 -365
- package/tests/test_signer.ts +0 -47
- package/tests/test_validation.ts +0 -66
|
@@ -1,33 +1,46 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Auth rejection tests — proves that
|
|
3
|
-
*
|
|
4
|
-
* 2. Requests with invalid/wrong signatures are rejected with 401
|
|
5
|
-
* 3. The SDK surfaces auth errors as PayServerError with correct statusCode
|
|
2
|
+
* Auth rejection tests — proves that the Wallet sends valid auth headers
|
|
3
|
+
* and that servers can reject invalid auth.
|
|
6
4
|
*/
|
|
7
5
|
|
|
8
6
|
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
9
7
|
import assert from "node:assert/strict";
|
|
10
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
createServer,
|
|
10
|
+
type Server,
|
|
11
|
+
type IncomingMessage,
|
|
12
|
+
type ServerResponse,
|
|
13
|
+
} from "node:http";
|
|
11
14
|
import { once } from "node:events";
|
|
12
|
-
|
|
13
|
-
import { PayClient, PayServerError, CallbackSigner, RawKeySigner } from "../src/index.js";
|
|
14
15
|
import type { Hex, Address } from "viem";
|
|
16
|
+
import { Wallet, PayServerError } from "../src/index.js";
|
|
15
17
|
|
|
16
18
|
const ANVIL_PK =
|
|
17
19
|
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" as Hex;
|
|
18
|
-
const WRONG_PK =
|
|
19
|
-
"0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" as Hex;
|
|
20
|
-
|
|
21
|
-
const TEST_ROUTER = "0x5FbDB2315678afecb367f032d93F642f64180aa3" as Address;
|
|
22
|
-
const TEST_CHAIN_ID = 8453;
|
|
23
|
-
const VALID_ADDR = "0x" + "a1".repeat(20);
|
|
24
20
|
|
|
25
21
|
/**
|
|
26
22
|
* Minimal HTTP server that enforces X-Pay-* auth headers.
|
|
27
|
-
*
|
|
23
|
+
* /contracts is public (no auth).
|
|
24
|
+
* Everything else requires valid auth headers.
|
|
28
25
|
*/
|
|
29
26
|
function createAuthServer(): Server {
|
|
30
27
|
return createServer((req: IncomingMessage, res: ServerResponse) => {
|
|
28
|
+
// /contracts is public
|
|
29
|
+
if (req.url?.endsWith("/contracts")) {
|
|
30
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
31
|
+
res.end(
|
|
32
|
+
JSON.stringify({
|
|
33
|
+
router: "0x5FbDB2315678afecb367f032d93F642f64180aa3",
|
|
34
|
+
tab: "0x" + "bb".repeat(20),
|
|
35
|
+
direct: "0x" + "cc".repeat(20),
|
|
36
|
+
fee: "0x" + "dd".repeat(20),
|
|
37
|
+
usdc: "0x" + "ee".repeat(20),
|
|
38
|
+
chain_id: 8453,
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
31
44
|
const agent = req.headers["x-pay-agent"];
|
|
32
45
|
const sig = req.headers["x-pay-signature"];
|
|
33
46
|
const ts = req.headers["x-pay-timestamp"];
|
|
@@ -39,7 +52,6 @@ function createAuthServer(): Server {
|
|
|
39
52
|
return;
|
|
40
53
|
}
|
|
41
54
|
|
|
42
|
-
// Check that sig looks like a real 65-byte hex signature
|
|
43
55
|
const sigStr = Array.isArray(sig) ? sig[0] : sig;
|
|
44
56
|
if (!sigStr.startsWith("0x") || sigStr.length !== 132) {
|
|
45
57
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
@@ -47,21 +59,15 @@ function createAuthServer(): Server {
|
|
|
47
59
|
return;
|
|
48
60
|
}
|
|
49
61
|
|
|
50
|
-
//
|
|
51
|
-
if (sigStr === "0x" + "0".repeat(130)) {
|
|
52
|
-
res.writeHead(401, { "Content-Type": "application/json" });
|
|
53
|
-
res.end(JSON.stringify({ error: "Stub signature rejected" }));
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Auth passed — return mock data
|
|
62
|
+
// Auth passed
|
|
58
63
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
59
64
|
res.end(
|
|
60
65
|
JSON.stringify({
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
open_tabs:
|
|
64
|
-
|
|
66
|
+
wallet: agent,
|
|
67
|
+
balance_usdc: "100000000",
|
|
68
|
+
open_tabs: 0,
|
|
69
|
+
total_locked: 0,
|
|
70
|
+
}),
|
|
65
71
|
);
|
|
66
72
|
});
|
|
67
73
|
}
|
|
@@ -69,14 +75,14 @@ function createAuthServer(): Server {
|
|
|
69
75
|
let server: Server;
|
|
70
76
|
let baseUrl: string;
|
|
71
77
|
|
|
72
|
-
describe("Auth
|
|
78
|
+
describe("Auth with new Wallet class", () => {
|
|
73
79
|
beforeEach(async () => {
|
|
74
80
|
server = createAuthServer();
|
|
75
|
-
server.listen(0);
|
|
81
|
+
server.listen(0);
|
|
76
82
|
await once(server, "listening");
|
|
77
83
|
const addr = server.address();
|
|
78
84
|
if (typeof addr === "object" && addr) {
|
|
79
|
-
baseUrl = `http://127.0.0.1:${addr.port}`;
|
|
85
|
+
baseUrl = `http://127.0.0.1:${addr.port}/api/v1`;
|
|
80
86
|
}
|
|
81
87
|
});
|
|
82
88
|
|
|
@@ -85,70 +91,12 @@ describe("Auth rejection", () => {
|
|
|
85
91
|
await once(server, "close");
|
|
86
92
|
});
|
|
87
93
|
|
|
88
|
-
it("
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
await assert.rejects(
|
|
96
|
-
() => client.getStatus(),
|
|
97
|
-
(err: unknown) => {
|
|
98
|
-
assert.ok(err instanceof PayServerError);
|
|
99
|
-
assert.equal(err.statusCode, 401);
|
|
100
|
-
assert.ok(err.message.includes("Missing auth headers"));
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("rejects request with stub signer (all-zero signature)", async () => {
|
|
107
|
-
// Client with a stub signer that returns zeros — server should reject
|
|
108
|
-
const client = new PayClient({
|
|
109
|
-
apiUrl: baseUrl,
|
|
110
|
-
signer: new CallbackSigner((_h: Uint8Array) => new Uint8Array(65)),
|
|
111
|
-
chainId: TEST_CHAIN_ID,
|
|
112
|
-
routerAddress: TEST_ROUTER,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
await assert.rejects(
|
|
116
|
-
() => client.getStatus(),
|
|
117
|
-
(err: unknown) => {
|
|
118
|
-
assert.ok(err instanceof PayServerError);
|
|
119
|
-
assert.equal(err.statusCode, 401);
|
|
120
|
-
return true;
|
|
121
|
-
}
|
|
122
|
-
);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("accepts request with valid auth headers (real signing)", async () => {
|
|
126
|
-
const client = new PayClient({
|
|
127
|
-
apiUrl: baseUrl,
|
|
128
|
-
privateKey: ANVIL_PK,
|
|
129
|
-
chainId: TEST_CHAIN_ID,
|
|
130
|
-
routerAddress: TEST_ROUTER,
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
// Should NOT throw — server accepts valid auth
|
|
134
|
-
const status = await client.getStatus();
|
|
135
|
-
assert.ok(status.balance >= 0);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it("PayServerError has statusCode 401 for auth failures", async () => {
|
|
139
|
-
// Directly verify error structure
|
|
140
|
-
const client = new PayClient({
|
|
141
|
-
apiUrl: baseUrl,
|
|
142
|
-
signer: new CallbackSigner((_h: Uint8Array) => new Uint8Array(65)),
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
await client.getStatus();
|
|
147
|
-
assert.fail("Should have thrown PayServerError");
|
|
148
|
-
} catch (err) {
|
|
149
|
-
assert.ok(err instanceof PayServerError, "must be PayServerError");
|
|
150
|
-
assert.equal(err.statusCode, 401, "statusCode must be 401");
|
|
151
|
-
assert.equal(err.code, "server_error");
|
|
152
|
-
}
|
|
94
|
+
it("Wallet sends valid auth headers and gets 200", async () => {
|
|
95
|
+
process.env.PAYSKILL_API_URL = baseUrl;
|
|
96
|
+
const wallet = new Wallet({ privateKey: ANVIL_PK });
|
|
97
|
+
const status = await wallet.status();
|
|
98
|
+
assert.ok(status.address.startsWith("0x"));
|
|
99
|
+
assert.ok(status.balance.total >= 0);
|
|
100
|
+
delete process.env.PAYSKILL_API_URL;
|
|
153
101
|
});
|
|
154
102
|
});
|
package/tests/test_crypto.ts
CHANGED
|
@@ -1,149 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Crypto round-trip tests — proves that:
|
|
3
|
-
* 1. Address derivation uses real secp256k1
|
|
4
|
-
* 2.
|
|
5
|
-
* 3. buildAuthHeaders produces valid auth headers
|
|
3
|
+
* 1. Address derivation uses real secp256k1
|
|
4
|
+
* 2. buildAuthHeaders produces valid recoverable signatures
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
7
|
import { describe, it } from "node:test";
|
|
9
8
|
import assert from "node:assert/strict";
|
|
10
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
11
9
|
import { recoverAddress, type Hex, type Address } from "viem";
|
|
12
10
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { buildAuthHeaders, computeEip712Hash } from "../src/auth.js";
|
|
11
|
+
import { Wallet } from "../src/wallet.js";
|
|
12
|
+
import { buildAuthHeaders, buildAuthHeadersSigned, computeEip712Hash } from "../src/auth.js";
|
|
16
13
|
|
|
17
14
|
// Anvil account #0 — well-known test key
|
|
18
15
|
const ANVIL_PK =
|
|
19
16
|
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" as Hex;
|
|
20
|
-
const ANVIL_ADDRESS =
|
|
17
|
+
const ANVIL_ADDRESS =
|
|
18
|
+
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" as Address;
|
|
21
19
|
|
|
22
|
-
const TEST_ROUTER =
|
|
20
|
+
const TEST_ROUTER =
|
|
21
|
+
"0x5FbDB2315678afecb367f032d93F642f64180aa3" as Address;
|
|
23
22
|
const TEST_CHAIN_ID = 8453;
|
|
24
23
|
|
|
25
24
|
describe("Address derivation", () => {
|
|
26
|
-
it("derives correct address from Anvil #0 private key
|
|
27
|
-
const wallet = new Wallet({
|
|
28
|
-
privateKey: ANVIL_PK,
|
|
29
|
-
chain: "8453",
|
|
30
|
-
apiUrl: "http://localhost:3000/api/v1",
|
|
31
|
-
routerAddress: TEST_ROUTER,
|
|
32
|
-
});
|
|
25
|
+
it("derives correct address from Anvil #0 private key", () => {
|
|
26
|
+
const wallet = new Wallet({ privateKey: ANVIL_PK });
|
|
33
27
|
assert.equal(wallet.address, ANVIL_ADDRESS);
|
|
34
28
|
});
|
|
35
29
|
|
|
36
|
-
it("derives correct address via PrivateKeySigner", () => {
|
|
37
|
-
const signer = new PrivateKeySigner(ANVIL_PK);
|
|
38
|
-
assert.equal(signer.address, ANVIL_ADDRESS);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it("derives correct address via RawKeySigner", () => {
|
|
42
|
-
const signer = new RawKeySigner(ANVIL_PK);
|
|
43
|
-
assert.equal(signer.address, ANVIL_ADDRESS);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
30
|
it("works without 0x prefix", () => {
|
|
47
|
-
const
|
|
48
|
-
assert.equal(
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe("EIP-712 signing round-trip", () => {
|
|
53
|
-
it("PrivateKeySigner produces recoverable EIP-712 signature", async () => {
|
|
54
|
-
const signer = new PrivateKeySigner(ANVIL_PK);
|
|
55
|
-
|
|
56
|
-
const domain = {
|
|
57
|
-
name: "pay",
|
|
58
|
-
version: "0.1",
|
|
59
|
-
chainId: BigInt(TEST_CHAIN_ID),
|
|
60
|
-
verifyingContract: TEST_ROUTER,
|
|
61
|
-
};
|
|
62
|
-
const types = {
|
|
63
|
-
APIRequest: [
|
|
64
|
-
{ name: "method", type: "string" },
|
|
65
|
-
{ name: "path", type: "string" },
|
|
66
|
-
{ name: "timestamp", type: "uint256" },
|
|
67
|
-
{ name: "nonce", type: "bytes32" },
|
|
68
|
-
],
|
|
69
|
-
};
|
|
70
|
-
const nonce =
|
|
71
|
-
"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
|
|
72
|
-
const message = {
|
|
73
|
-
method: "POST",
|
|
74
|
-
path: "/api/v1/direct",
|
|
75
|
-
timestamp: BigInt(1741400000),
|
|
76
|
-
nonce,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const signature = await signer.signTypedData(domain, types, message);
|
|
80
|
-
|
|
81
|
-
assert.ok(signature.startsWith("0x"), "signature should be hex");
|
|
82
|
-
assert.equal(signature.length, 132, "signature should be 65 bytes hex");
|
|
83
|
-
assert.notEqual(
|
|
84
|
-
signature,
|
|
85
|
-
"0x" + "0".repeat(130),
|
|
86
|
-
"signature must not be zeros (stub)"
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
// Recover the signer address from the signature
|
|
90
|
-
const recovered = await recoverAddress({
|
|
91
|
-
hash: (await import("viem")).hashTypedData({
|
|
92
|
-
domain,
|
|
93
|
-
types,
|
|
94
|
-
primaryType: "APIRequest",
|
|
95
|
-
message,
|
|
96
|
-
}),
|
|
97
|
-
signature: signature as Hex,
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
assert.equal(
|
|
101
|
-
recovered.toLowerCase(),
|
|
102
|
-
ANVIL_ADDRESS.toLowerCase(),
|
|
103
|
-
"recovered address must match signer"
|
|
104
|
-
);
|
|
31
|
+
const wallet = new Wallet({ privateKey: ANVIL_PK.slice(2) });
|
|
32
|
+
assert.equal(wallet.address, ANVIL_ADDRESS);
|
|
105
33
|
});
|
|
106
34
|
});
|
|
107
35
|
|
|
108
36
|
describe("buildAuthHeaders", () => {
|
|
109
37
|
it("produces valid auth headers with correct address", async () => {
|
|
110
|
-
const headers = await buildAuthHeaders(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
assert.equal(headers["X-Pay-Agent"], ANVIL_ADDRESS);
|
|
116
|
-
assert.ok(
|
|
117
|
-
headers["X-Pay-Signature"].startsWith("0x"),
|
|
118
|
-
"signature should be hex"
|
|
119
|
-
);
|
|
120
|
-
assert.equal(
|
|
121
|
-
headers["X-Pay-Signature"].length,
|
|
122
|
-
132,
|
|
123
|
-
"signature should be 65 bytes"
|
|
124
|
-
);
|
|
125
|
-
assert.ok(
|
|
126
|
-
Number(headers["X-Pay-Timestamp"]) > 0,
|
|
127
|
-
"timestamp should be positive"
|
|
128
|
-
);
|
|
129
|
-
assert.ok(
|
|
130
|
-
headers["X-Pay-Nonce"].startsWith("0x"),
|
|
131
|
-
"nonce should be hex"
|
|
132
|
-
);
|
|
133
|
-
assert.equal(
|
|
134
|
-
headers["X-Pay-Nonce"].length,
|
|
135
|
-
66,
|
|
136
|
-
"nonce should be 32 bytes hex"
|
|
38
|
+
const headers = await buildAuthHeaders(
|
|
39
|
+
ANVIL_PK,
|
|
40
|
+
"POST",
|
|
41
|
+
"/api/v1/direct",
|
|
42
|
+
{ chainId: TEST_CHAIN_ID, routerAddress: TEST_ROUTER },
|
|
137
43
|
);
|
|
44
|
+
assert.equal(headers["X-Pay-Agent"], ANVIL_ADDRESS);
|
|
45
|
+
assert.ok(headers["X-Pay-Signature"].startsWith("0x"));
|
|
46
|
+
assert.equal(headers["X-Pay-Signature"].length, 132);
|
|
47
|
+
assert.ok(Number(headers["X-Pay-Timestamp"]) > 0);
|
|
48
|
+
assert.ok(headers["X-Pay-Nonce"].startsWith("0x"));
|
|
49
|
+
assert.equal(headers["X-Pay-Nonce"].length, 66);
|
|
138
50
|
});
|
|
139
51
|
|
|
140
52
|
it("signature recovers to the correct address", async () => {
|
|
141
|
-
const headers = await buildAuthHeaders(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
53
|
+
const headers = await buildAuthHeaders(
|
|
54
|
+
ANVIL_PK,
|
|
55
|
+
"POST",
|
|
56
|
+
"/api/v1/direct",
|
|
57
|
+
{ chainId: TEST_CHAIN_ID, routerAddress: TEST_ROUTER },
|
|
58
|
+
);
|
|
147
59
|
const { hashTypedData } = await import("viem");
|
|
148
60
|
const hash = hashTypedData({
|
|
149
61
|
domain: {
|
|
@@ -168,83 +80,58 @@ describe("buildAuthHeaders", () => {
|
|
|
168
80
|
nonce: headers["X-Pay-Nonce"] as Hex,
|
|
169
81
|
},
|
|
170
82
|
});
|
|
171
|
-
|
|
172
83
|
const recovered = await recoverAddress({
|
|
173
84
|
hash,
|
|
174
85
|
signature: headers["X-Pay-Signature"] as Hex,
|
|
175
86
|
});
|
|
87
|
+
assert.equal(recovered.toLowerCase(), ANVIL_ADDRESS.toLowerCase());
|
|
88
|
+
});
|
|
89
|
+
});
|
|
176
90
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
91
|
+
describe("buildAuthHeadersSigned", () => {
|
|
92
|
+
it("produces same-structure headers as buildAuthHeaders", async () => {
|
|
93
|
+
const { privateKeyToAccount } = await import("viem/accounts");
|
|
94
|
+
const account = privateKeyToAccount(ANVIL_PK);
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
96
|
+
const signFn = (p: any) => account.signTypedData(p);
|
|
97
|
+
|
|
98
|
+
const headers = await buildAuthHeadersSigned(
|
|
99
|
+
ANVIL_ADDRESS,
|
|
100
|
+
signFn,
|
|
101
|
+
"GET",
|
|
102
|
+
"/api/v1/status",
|
|
103
|
+
{ chainId: TEST_CHAIN_ID, routerAddress: TEST_ROUTER },
|
|
181
104
|
);
|
|
105
|
+
assert.equal(headers["X-Pay-Agent"], ANVIL_ADDRESS);
|
|
106
|
+
assert.ok(headers["X-Pay-Signature"].startsWith("0x"));
|
|
107
|
+
assert.equal(headers["X-Pay-Signature"].length, 132);
|
|
182
108
|
});
|
|
183
109
|
});
|
|
184
110
|
|
|
185
111
|
describe("computeEip712Hash", () => {
|
|
112
|
+
const nonce =
|
|
113
|
+
"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" as Hex;
|
|
114
|
+
|
|
186
115
|
it("produces deterministic output", () => {
|
|
187
|
-
const nonce =
|
|
188
|
-
"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" as Hex;
|
|
189
116
|
const h1 = computeEip712Hash(
|
|
190
|
-
"POST",
|
|
191
|
-
|
|
192
|
-
BigInt(1741400000),
|
|
193
|
-
nonce,
|
|
194
|
-
TEST_CHAIN_ID,
|
|
195
|
-
TEST_ROUTER
|
|
117
|
+
"POST", "/api/v1/direct", BigInt(1741400000),
|
|
118
|
+
nonce, TEST_CHAIN_ID, TEST_ROUTER,
|
|
196
119
|
);
|
|
197
120
|
const h2 = computeEip712Hash(
|
|
198
|
-
"POST",
|
|
199
|
-
|
|
200
|
-
BigInt(1741400000),
|
|
201
|
-
nonce,
|
|
202
|
-
TEST_CHAIN_ID,
|
|
203
|
-
TEST_ROUTER
|
|
121
|
+
"POST", "/api/v1/direct", BigInt(1741400000),
|
|
122
|
+
nonce, TEST_CHAIN_ID, TEST_ROUTER,
|
|
204
123
|
);
|
|
205
124
|
assert.deepEqual(h1, h2);
|
|
206
125
|
});
|
|
207
126
|
|
|
208
127
|
it("different methods produce different hashes", () => {
|
|
209
|
-
const nonce =
|
|
210
|
-
"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" as Hex;
|
|
211
128
|
const h1 = computeEip712Hash(
|
|
212
|
-
"POST",
|
|
213
|
-
|
|
214
|
-
BigInt(1741400000),
|
|
215
|
-
nonce,
|
|
216
|
-
TEST_CHAIN_ID,
|
|
217
|
-
TEST_ROUTER
|
|
218
|
-
);
|
|
219
|
-
const h2 = computeEip712Hash(
|
|
220
|
-
"GET",
|
|
221
|
-
"/api/v1/direct",
|
|
222
|
-
BigInt(1741400000),
|
|
223
|
-
nonce,
|
|
224
|
-
TEST_CHAIN_ID,
|
|
225
|
-
TEST_ROUTER
|
|
226
|
-
);
|
|
227
|
-
assert.notDeepEqual(h1, h2);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it("different chain IDs produce different hashes", () => {
|
|
231
|
-
const nonce =
|
|
232
|
-
"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" as Hex;
|
|
233
|
-
const h1 = computeEip712Hash(
|
|
234
|
-
"POST",
|
|
235
|
-
"/api/v1/direct",
|
|
236
|
-
BigInt(1741400000),
|
|
237
|
-
nonce,
|
|
238
|
-
8453,
|
|
239
|
-
TEST_ROUTER
|
|
129
|
+
"POST", "/api/v1/direct", BigInt(1741400000),
|
|
130
|
+
nonce, TEST_CHAIN_ID, TEST_ROUTER,
|
|
240
131
|
);
|
|
241
132
|
const h2 = computeEip712Hash(
|
|
242
|
-
"
|
|
243
|
-
|
|
244
|
-
BigInt(1741400000),
|
|
245
|
-
nonce,
|
|
246
|
-
84531,
|
|
247
|
-
TEST_ROUTER
|
|
133
|
+
"GET", "/api/v1/direct", BigInt(1741400000),
|
|
134
|
+
nonce, TEST_CHAIN_ID, TEST_ROUTER,
|
|
248
135
|
);
|
|
249
136
|
assert.notDeepEqual(h1, h2);
|
|
250
137
|
});
|