@pay-skill/sdk 0.1.8 → 0.1.10
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 +135 -104
- package/dist/wallet.d.ts.map +1 -1
- package/dist/wallet.js +683 -280
- 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 +1074 -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
package/tests/test_ows_signer.ts
DELETED
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OWS Signer unit tests.
|
|
3
|
-
*
|
|
4
|
-
* Uses a mock OWS module — no real @open-wallet-standard/core needed.
|
|
5
|
-
* Tests construction, EIP-712 typed data building, signature concatenation,
|
|
6
|
-
* BigInt serialization, error paths, and security (no key leakage).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { describe, it } from "node:test";
|
|
10
|
-
import assert from "node:assert/strict";
|
|
11
|
-
import { OwsSigner } from "../src/ows-signer.js";
|
|
12
|
-
|
|
13
|
-
// ── Mock OWS module ──────────────────────────────────────────────────
|
|
14
|
-
|
|
15
|
-
interface SignCall {
|
|
16
|
-
wallet: string;
|
|
17
|
-
chain: string;
|
|
18
|
-
json: string;
|
|
19
|
-
passphrase?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function createMockOws(options?: {
|
|
23
|
-
accounts?: Array<{ chainId: string; address: string; derivationPath: string }>;
|
|
24
|
-
signature?: string;
|
|
25
|
-
recoveryId?: number;
|
|
26
|
-
}) {
|
|
27
|
-
const calls: SignCall[] = [];
|
|
28
|
-
const accounts = options?.accounts ?? [
|
|
29
|
-
{
|
|
30
|
-
chainId: "eip155:8453",
|
|
31
|
-
address: "0x1234567890abcdef1234567890abcdef12345678",
|
|
32
|
-
derivationPath: "m/44'/60'/0'/0/0",
|
|
33
|
-
},
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
calls,
|
|
38
|
-
getWallet(nameOrId: string) {
|
|
39
|
-
return {
|
|
40
|
-
id: `id-${nameOrId}`,
|
|
41
|
-
name: nameOrId,
|
|
42
|
-
accounts,
|
|
43
|
-
createdAt: "2026-04-01T00:00:00Z",
|
|
44
|
-
};
|
|
45
|
-
},
|
|
46
|
-
signTypedData(
|
|
47
|
-
wallet: string,
|
|
48
|
-
chain: string,
|
|
49
|
-
typedDataJson: string,
|
|
50
|
-
passphrase?: string,
|
|
51
|
-
) {
|
|
52
|
-
calls.push({ wallet, chain, json: typedDataJson, passphrase });
|
|
53
|
-
return {
|
|
54
|
-
signature: options?.signature ?? "aa".repeat(64),
|
|
55
|
-
recoveryId: options?.recoveryId ?? 0,
|
|
56
|
-
};
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// ── Construction ─────────────────────────────────────────────────────
|
|
62
|
-
|
|
63
|
-
describe("OwsSigner.create", () => {
|
|
64
|
-
it("creates signer with eip155 chain id", async () => {
|
|
65
|
-
const mock = createMockOws();
|
|
66
|
-
const signer = await OwsSigner.create({
|
|
67
|
-
walletId: "pay-test",
|
|
68
|
-
_owsModule: mock,
|
|
69
|
-
});
|
|
70
|
-
assert.equal(
|
|
71
|
-
signer.address,
|
|
72
|
-
"0x1234567890abcdef1234567890abcdef12345678",
|
|
73
|
-
);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it("creates signer with evm chain id", async () => {
|
|
77
|
-
const mock = createMockOws({
|
|
78
|
-
accounts: [
|
|
79
|
-
{
|
|
80
|
-
chainId: "evm",
|
|
81
|
-
address: "0xcafe",
|
|
82
|
-
derivationPath: "m/44'/60'/0'/0/0",
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
});
|
|
86
|
-
const signer = await OwsSigner.create({
|
|
87
|
-
walletId: "pay-evm",
|
|
88
|
-
_owsModule: mock,
|
|
89
|
-
});
|
|
90
|
-
assert.equal(signer.address, "0xcafe");
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("throws when no EVM account found", async () => {
|
|
94
|
-
const mock = createMockOws({
|
|
95
|
-
accounts: [
|
|
96
|
-
{
|
|
97
|
-
chainId: "solana",
|
|
98
|
-
address: "Sol123",
|
|
99
|
-
derivationPath: "m/44'/501'/0'/0'",
|
|
100
|
-
},
|
|
101
|
-
],
|
|
102
|
-
});
|
|
103
|
-
await assert.rejects(
|
|
104
|
-
() => OwsSigner.create({ walletId: "pay-sol", _owsModule: mock }),
|
|
105
|
-
{ message: /No EVM account found/ },
|
|
106
|
-
);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("throws when no accounts at all", async () => {
|
|
110
|
-
const mock = createMockOws({ accounts: [] });
|
|
111
|
-
await assert.rejects(
|
|
112
|
-
() => OwsSigner.create({ walletId: "pay-empty", _owsModule: mock }),
|
|
113
|
-
{ message: /No EVM account found/ },
|
|
114
|
-
);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it("throws clear error when OWS not installed or wallet missing", async () => {
|
|
118
|
-
// Without _owsModule, create() will try dynamic import.
|
|
119
|
-
// If OWS is installed (e.g. peer dep in CI), it throws "wallet not found".
|
|
120
|
-
// If OWS is NOT installed, it throws "not installed".
|
|
121
|
-
await assert.rejects(
|
|
122
|
-
() => OwsSigner.create({ walletId: "pay-missing" }),
|
|
123
|
-
{ message: /not installed|wallet not found/ },
|
|
124
|
-
);
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
// ── signTypedData ────────────────────────────────────────────────────
|
|
129
|
-
|
|
130
|
-
describe("OwsSigner.signTypedData", () => {
|
|
131
|
-
const domain = {
|
|
132
|
-
name: "Pay",
|
|
133
|
-
version: "1",
|
|
134
|
-
chainId: 8453,
|
|
135
|
-
verifyingContract: "0xrouter" as const,
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const types = {
|
|
139
|
-
Request: [
|
|
140
|
-
{ name: "method", type: "string" },
|
|
141
|
-
{ name: "path", type: "string" },
|
|
142
|
-
],
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const value = { method: "POST", path: "/api/v1/direct" };
|
|
146
|
-
|
|
147
|
-
it("builds EIP-712 JSON with EIP712Domain injected", async () => {
|
|
148
|
-
const mock = createMockOws();
|
|
149
|
-
const signer = await OwsSigner.create({
|
|
150
|
-
walletId: "pay-test",
|
|
151
|
-
_owsModule: mock,
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
await signer.signTypedData(domain, types, value);
|
|
155
|
-
|
|
156
|
-
assert.equal(mock.calls.length, 1);
|
|
157
|
-
const parsed = JSON.parse(mock.calls[0].json);
|
|
158
|
-
|
|
159
|
-
// EIP712Domain should be auto-generated from domain fields
|
|
160
|
-
assert.deepStrictEqual(parsed.types.EIP712Domain, [
|
|
161
|
-
{ name: "name", type: "string" },
|
|
162
|
-
{ name: "version", type: "string" },
|
|
163
|
-
{ name: "chainId", type: "uint256" },
|
|
164
|
-
{ name: "verifyingContract", type: "address" },
|
|
165
|
-
]);
|
|
166
|
-
|
|
167
|
-
// Original types preserved
|
|
168
|
-
assert.deepStrictEqual(parsed.types.Request, types.Request);
|
|
169
|
-
|
|
170
|
-
// Primary type derived from first non-EIP712Domain key
|
|
171
|
-
assert.equal(parsed.primaryType, "Request");
|
|
172
|
-
|
|
173
|
-
// Domain and message passed through
|
|
174
|
-
assert.deepStrictEqual(parsed.domain, domain);
|
|
175
|
-
assert.deepStrictEqual(parsed.message, value);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it("passes chain as evm always", async () => {
|
|
179
|
-
const mock = createMockOws();
|
|
180
|
-
const signer = await OwsSigner.create({
|
|
181
|
-
walletId: "pay-test",
|
|
182
|
-
_owsModule: mock,
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
await signer.signTypedData(domain, types, value);
|
|
186
|
-
assert.equal(mock.calls[0].chain, "evm");
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
it("passes API key as passphrase", async () => {
|
|
190
|
-
const mock = createMockOws();
|
|
191
|
-
const signer = await OwsSigner.create({
|
|
192
|
-
walletId: "pay-test",
|
|
193
|
-
owsApiKey: "ows_key_secret123",
|
|
194
|
-
_owsModule: mock,
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
await signer.signTypedData(domain, types, value);
|
|
198
|
-
assert.equal(mock.calls[0].passphrase, "ows_key_secret123");
|
|
199
|
-
|
|
200
|
-
// API key must NOT appear in the JSON payload
|
|
201
|
-
assert.ok(!mock.calls[0].json.includes("ows_key_secret123"));
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it("only includes domain fields that are present", async () => {
|
|
205
|
-
const mock = createMockOws();
|
|
206
|
-
const signer = await OwsSigner.create({
|
|
207
|
-
walletId: "pay-test",
|
|
208
|
-
_owsModule: mock,
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
// Domain with only name and chainId
|
|
212
|
-
await signer.signTypedData(
|
|
213
|
-
{ name: "Pay", chainId: 8453 },
|
|
214
|
-
types,
|
|
215
|
-
value,
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
const parsed = JSON.parse(mock.calls[0].json);
|
|
219
|
-
assert.deepStrictEqual(parsed.types.EIP712Domain, [
|
|
220
|
-
{ name: "name", type: "string" },
|
|
221
|
-
{ name: "chainId", type: "uint256" },
|
|
222
|
-
]);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it("serializes BigInt values to strings", async () => {
|
|
226
|
-
const mock = createMockOws();
|
|
227
|
-
const signer = await OwsSigner.create({
|
|
228
|
-
walletId: "pay-test",
|
|
229
|
-
_owsModule: mock,
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
await signer.signTypedData(domain, types, {
|
|
233
|
-
method: "POST",
|
|
234
|
-
path: "/direct",
|
|
235
|
-
amount: 5000000n,
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
const parsed = JSON.parse(mock.calls[0].json);
|
|
239
|
-
assert.equal(parsed.message.amount, "5000000");
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
// ── Signature concatenation ──────────────────────────────────────────
|
|
244
|
-
|
|
245
|
-
describe("signature concatenation", () => {
|
|
246
|
-
it("appends v=27 when recoveryId=0", async () => {
|
|
247
|
-
const mock = createMockOws({
|
|
248
|
-
signature: "aa".repeat(64), // 128 hex = r+s only
|
|
249
|
-
recoveryId: 0,
|
|
250
|
-
});
|
|
251
|
-
const signer = await OwsSigner.create({
|
|
252
|
-
walletId: "pay-test",
|
|
253
|
-
_owsModule: mock,
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
const sig = await signer.signTypedData({}, { R: [] }, {});
|
|
257
|
-
assert.ok(sig.startsWith("0x"));
|
|
258
|
-
assert.equal(sig.length, 2 + 130); // 0x + 64r + 64s + 2v
|
|
259
|
-
assert.equal(sig.slice(-2), "1b"); // 27 = 0x1b
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
it("appends v=28 when recoveryId=1", async () => {
|
|
263
|
-
const mock = createMockOws({
|
|
264
|
-
signature: "bb".repeat(64),
|
|
265
|
-
recoveryId: 1,
|
|
266
|
-
});
|
|
267
|
-
const signer = await OwsSigner.create({
|
|
268
|
-
walletId: "pay-test",
|
|
269
|
-
_owsModule: mock,
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
const sig = await signer.signTypedData({}, { R: [] }, {});
|
|
273
|
-
assert.equal(sig.slice(-2), "1c"); // 28 = 0x1c
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
it("passes through 130-char RSV signature as-is", async () => {
|
|
277
|
-
const rsv = "cc".repeat(65); // 130 hex = already has v
|
|
278
|
-
const mock = createMockOws({ signature: rsv });
|
|
279
|
-
const signer = await OwsSigner.create({
|
|
280
|
-
walletId: "pay-test",
|
|
281
|
-
_owsModule: mock,
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
const sig = await signer.signTypedData({}, { R: [] }, {});
|
|
285
|
-
assert.equal(sig, `0x${rsv}`);
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it("strips 0x prefix from OWS signature", async () => {
|
|
289
|
-
const mock = createMockOws({
|
|
290
|
-
signature: "0x" + "dd".repeat(64),
|
|
291
|
-
recoveryId: 0,
|
|
292
|
-
});
|
|
293
|
-
const signer = await OwsSigner.create({
|
|
294
|
-
walletId: "pay-test",
|
|
295
|
-
_owsModule: mock,
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
const sig = await signer.signTypedData({}, { R: [] }, {});
|
|
299
|
-
assert.ok(!sig.includes("0x0x")); // no double prefix
|
|
300
|
-
assert.equal(sig.length, 2 + 130);
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
it("defaults recoveryId to 0 when undefined", async () => {
|
|
304
|
-
const mock = createMockOws({
|
|
305
|
-
signature: "ee".repeat(64),
|
|
306
|
-
recoveryId: undefined,
|
|
307
|
-
});
|
|
308
|
-
const signer = await OwsSigner.create({
|
|
309
|
-
walletId: "pay-test",
|
|
310
|
-
_owsModule: mock,
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
const sig = await signer.signTypedData({}, { R: [] }, {});
|
|
314
|
-
assert.equal(sig.slice(-2), "1b"); // v=27
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
// ── sign() rejection ─────────────────────────────────────────────────
|
|
319
|
-
|
|
320
|
-
describe("sign() raw hash rejection", () => {
|
|
321
|
-
it("throws because OWS only supports EIP-712", async () => {
|
|
322
|
-
const mock = createMockOws();
|
|
323
|
-
const signer = await OwsSigner.create({
|
|
324
|
-
walletId: "pay-test",
|
|
325
|
-
_owsModule: mock,
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
assert.throws(
|
|
329
|
-
() => signer.sign(new Uint8Array(32)),
|
|
330
|
-
{ message: /does not support raw hash signing/ },
|
|
331
|
-
);
|
|
332
|
-
});
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
// ── Security ─────────────────────────────────────────────────────────
|
|
336
|
-
|
|
337
|
-
describe("security", () => {
|
|
338
|
-
it("toJSON does not expose API key", async () => {
|
|
339
|
-
const mock = createMockOws();
|
|
340
|
-
const signer = await OwsSigner.create({
|
|
341
|
-
walletId: "pay-test",
|
|
342
|
-
owsApiKey: "ows_key_topsecret",
|
|
343
|
-
_owsModule: mock,
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
const json = signer.toJSON();
|
|
347
|
-
assert.ok(!JSON.stringify(json).includes("topsecret"));
|
|
348
|
-
assert.equal(json.walletId, "pay-test");
|
|
349
|
-
assert.ok(json.address);
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
it("inspect does not expose API key", async () => {
|
|
353
|
-
const mock = createMockOws();
|
|
354
|
-
const signer = await OwsSigner.create({
|
|
355
|
-
walletId: "pay-test",
|
|
356
|
-
owsApiKey: "ows_key_topsecret",
|
|
357
|
-
_owsModule: mock,
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
const inspectFn = signer[Symbol.for("nodejs.util.inspect.custom")] as () => string;
|
|
361
|
-
const output = inspectFn.call(signer);
|
|
362
|
-
assert.ok(!output.includes("topsecret"));
|
|
363
|
-
assert.ok(output.includes("pay-test"));
|
|
364
|
-
});
|
|
365
|
-
});
|
package/tests/test_signer.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { describe, it } from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import {
|
|
4
|
-
CallbackSigner,
|
|
5
|
-
CliSigner,
|
|
6
|
-
RawKeySigner,
|
|
7
|
-
createSigner,
|
|
8
|
-
} from "../src/signer.js";
|
|
9
|
-
|
|
10
|
-
describe("CallbackSigner", () => {
|
|
11
|
-
it("delegates to callback", () => {
|
|
12
|
-
const sig = new Uint8Array(65).fill(1);
|
|
13
|
-
const signer = new CallbackSigner(() => sig);
|
|
14
|
-
const result = signer.sign(new Uint8Array(32));
|
|
15
|
-
assert.deepEqual(result, sig);
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
describe("createSigner", () => {
|
|
20
|
-
it("creates CliSigner for cli mode", () => {
|
|
21
|
-
const signer = createSigner("cli");
|
|
22
|
-
assert.ok(signer instanceof CliSigner);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("throws for raw mode without key", () => {
|
|
26
|
-
const originalKey = process.env.PAYSKILL_KEY;
|
|
27
|
-
delete process.env.PAYSKILL_KEY;
|
|
28
|
-
assert.throws(() => createSigner("raw"), /No key/);
|
|
29
|
-
if (originalKey) process.env.PAYSKILL_KEY = originalKey;
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("creates RawKeySigner with key", () => {
|
|
33
|
-
const signer = createSigner("raw", { key: "0x" + "ab".repeat(32) });
|
|
34
|
-
assert.ok(signer instanceof RawKeySigner);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("creates CallbackSigner for custom mode", () => {
|
|
38
|
-
const signer = createSigner("custom", {
|
|
39
|
-
callback: () => new Uint8Array(65),
|
|
40
|
-
});
|
|
41
|
-
assert.ok(signer instanceof CallbackSigner);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("throws for custom mode without callback", () => {
|
|
45
|
-
assert.throws(() => createSigner("custom"), /callback/);
|
|
46
|
-
});
|
|
47
|
-
});
|
package/tests/test_validation.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { describe, it } from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { PayClient } from "../src/client.js";
|
|
4
|
-
import { PayValidationError } from "../src/errors.js";
|
|
5
|
-
import { CallbackSigner } from "../src/signer.js";
|
|
6
|
-
|
|
7
|
-
const VALID_ADDR = "0x" + "a1".repeat(20);
|
|
8
|
-
const dummySigner = new CallbackSigner(() => new Uint8Array(65));
|
|
9
|
-
|
|
10
|
-
const client = new PayClient({
|
|
11
|
-
apiUrl: "http://localhost:9999",
|
|
12
|
-
signer: dummySigner,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
describe("payDirect validation", () => {
|
|
16
|
-
it("rejects invalid address", async () => {
|
|
17
|
-
await assert.rejects(
|
|
18
|
-
() => client.payDirect("not-an-address", 1_000_000),
|
|
19
|
-
PayValidationError
|
|
20
|
-
);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("rejects amount below minimum", async () => {
|
|
24
|
-
await assert.rejects(
|
|
25
|
-
() => client.payDirect(VALID_ADDR, 500_000),
|
|
26
|
-
PayValidationError
|
|
27
|
-
);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("accepts valid inputs (fails on network, not validation)", async () => {
|
|
31
|
-
// This should fail with a network error, not validation
|
|
32
|
-
await assert.rejects(
|
|
33
|
-
() => client.payDirect(VALID_ADDR, 1_000_000),
|
|
34
|
-
(err: Error) => {
|
|
35
|
-
assert.ok(!(err instanceof PayValidationError));
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
describe("openTab validation", () => {
|
|
44
|
-
it("rejects amount below $5 minimum", async () => {
|
|
45
|
-
await assert.rejects(
|
|
46
|
-
() =>
|
|
47
|
-
client.openTab(VALID_ADDR, 1_000_000, { maxChargePerCall: 100_000 }),
|
|
48
|
-
PayValidationError
|
|
49
|
-
);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("rejects zero maxChargePerCall", async () => {
|
|
53
|
-
await assert.rejects(
|
|
54
|
-
() => client.openTab(VALID_ADDR, 10_000_000, { maxChargePerCall: 0 }),
|
|
55
|
-
PayValidationError
|
|
56
|
-
);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("rejects invalid provider address", async () => {
|
|
60
|
-
await assert.rejects(
|
|
61
|
-
() =>
|
|
62
|
-
client.openTab("bad-addr", 10_000_000, { maxChargePerCall: 500_000 }),
|
|
63
|
-
PayValidationError
|
|
64
|
-
);
|
|
65
|
-
});
|
|
66
|
-
});
|