@piprail/sdk 1.0.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.
@@ -0,0 +1,346 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+ var _chunkWQWNPAYQcjs = require('./chunk-WQWNPAYQ.cjs');
10
+
11
+ // src/drivers/near/index.ts
12
+ var _nearapijs = require('near-api-js');
13
+
14
+ // src/drivers/near/chains.ts
15
+ var NEAR_DECIMALS = 24;
16
+ var NEAR_MAINNET = {
17
+ caip2: "near:mainnet",
18
+ defaultRpc: "https://free.rpc.fastnear.com",
19
+ tokens: {
20
+ // Circle USDC — native (NOT the .factory.bridge.near bridge). Contract + 6dp
21
+ // verified live via ft_metadata before shipping.
22
+ USDC: {
23
+ contractId: "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1",
24
+ decimals: 6,
25
+ symbol: "USDC"
26
+ },
27
+ // Tether USDt — native (Tether's official tether-token.near account). On-chain
28
+ // symbol is "USDt"; contract + 6dp verified live via ft_metadata before shipping.
29
+ USDT: {
30
+ contractId: "usdt.tether-token.near",
31
+ decimals: 6,
32
+ symbol: "USDT"
33
+ }
34
+ }
35
+ };
36
+
37
+ // src/drivers/near/pay.ts
38
+ var FT_TRANSFER_GAS = 30000000000000n;
39
+ var ONE_YOCTO = 1n;
40
+ async function payNear(params) {
41
+ const { client, accept, gas } = params;
42
+ try {
43
+ const res = await client.ftTransfer({
44
+ contractId: accept.asset,
45
+ receiverId: accept.payTo,
46
+ amount: accept.amount,
47
+ memo: accept.extra.nonce,
48
+ // nonce binding (Template A)
49
+ gas: _nullishCoalesce(gas, () => ( FT_TRANSFER_GAS)),
50
+ deposit: ONE_YOCTO
51
+ });
52
+ return res.hash;
53
+ } catch (err) {
54
+ if (isNearRegistrationError(err)) {
55
+ throw new Error(
56
+ `NEAR ft_transfer failed: recipient ${accept.payTo} isn't registered on token ${accept.asset} (NEP-145 storage_deposit). Register it once (\u22480.00125 NEAR) before it can receive.`,
57
+ { cause: err }
58
+ );
59
+ }
60
+ if (isNearAffordability(err)) {
61
+ throw new (0, _chunkWQWNPAYQcjs.InsufficientFundsError)(
62
+ err instanceof Error ? err.message : "Insufficient NEAR balance for the payment.",
63
+ { cause: err }
64
+ );
65
+ }
66
+ throw _nullishCoalesce(_chunkWQWNPAYQcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
67
+ }
68
+ }
69
+ function isNearRegistrationError(err) {
70
+ const m = err instanceof Error ? err.message : String(err);
71
+ return /not registered|storage_?deposit|The account .* is not registered/i.test(m);
72
+ }
73
+ function isNearAffordability(err) {
74
+ const m = err instanceof Error ? err.message : String(err);
75
+ return /not enough|doesn't have enough|does not have enough|lack ?balance|exceeds .*balance|insufficient/i.test(m);
76
+ }
77
+
78
+ // src/drivers/near/verify.ts
79
+ function parseFtTransferEvent(line) {
80
+ const marker = "EVENT_JSON:";
81
+ const i = line.indexOf(marker);
82
+ if (i < 0) return null;
83
+ try {
84
+ const ev = JSON.parse(line.slice(i + marker.length));
85
+ if (ev.standard === "nep141" && ev.event === "ft_transfer" && Array.isArray(ev.data)) {
86
+ return ev.data;
87
+ }
88
+ } catch (e) {
89
+ }
90
+ return null;
91
+ }
92
+ async function verifyNear(params) {
93
+ const { reader, hash, senderId, accept } = params;
94
+ const required = BigInt(accept.amount);
95
+ const nonce = accept.extra.nonce;
96
+ let tx;
97
+ try {
98
+ tx = await reader.txStatus(hash, senderId);
99
+ } catch (e2) {
100
+ return txNotFound(hash);
101
+ }
102
+ if (!tx) return txNotFound(hash);
103
+ if (!tx.success) {
104
+ return { ok: false, error: "tx_reverted", detail: `NEAR tx ${hash} failed on-chain.` };
105
+ }
106
+ if (typeof tx.timestampMs === "number") {
107
+ const ageSeconds = Math.floor(Date.now() / 1e3) - Math.floor(tx.timestampMs / 1e3);
108
+ if (ageSeconds > accept.maxTimeoutSeconds) {
109
+ return {
110
+ ok: false,
111
+ error: "payment_expired",
112
+ detail: `Payment is ${ageSeconds}s old; max allowed is ${accept.maxTimeoutSeconds}s.`
113
+ };
114
+ }
115
+ }
116
+ let paid = 0n;
117
+ let payer = "";
118
+ for (const r of tx.receipts) {
119
+ if (r.executorId !== accept.asset) continue;
120
+ for (const line of r.logs) {
121
+ const data = parseFtTransferEvent(line);
122
+ if (!data) continue;
123
+ for (const d of data) {
124
+ if (d.new_owner_id === accept.payTo && (_nullishCoalesce(d.memo, () => ( ""))) === nonce) {
125
+ try {
126
+ paid += BigInt(_nullishCoalesce(d.amount, () => ( "0")));
127
+ } catch (e3) {
128
+ }
129
+ if (!payer) payer = _nullishCoalesce(d.old_owner_id, () => ( ""));
130
+ }
131
+ }
132
+ }
133
+ }
134
+ if (paid < required) {
135
+ return {
136
+ ok: false,
137
+ error: "transfer_not_found",
138
+ detail: `No NEP-141 ft_transfer of >= ${required} (token ${accept.asset}) to ${accept.payTo} carrying our nonce in ${hash}.`
139
+ };
140
+ }
141
+ return {
142
+ ok: true,
143
+ receipt: {
144
+ scheme: "onchain-proof",
145
+ success: true,
146
+ network: accept.network,
147
+ transaction: hash,
148
+ asset: accept.asset,
149
+ amount: accept.amount,
150
+ payer,
151
+ payTo: accept.payTo,
152
+ verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
153
+ }
154
+ };
155
+ }
156
+ function txNotFound(hash) {
157
+ return {
158
+ ok: false,
159
+ error: "tx_not_found",
160
+ detail: `NEAR tx ${hash} not found or not yet executed \u2014 retry.`
161
+ };
162
+ }
163
+
164
+ // src/drivers/near/wallet.ts
165
+
166
+ function assertNearWallet(wallet, network) {
167
+ if (typeof wallet !== "object" || wallet === null) {
168
+ throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
169
+ `chain ${network} is NEAR; wallet must be { accountId, privateKey } (privateKey = ed25519:\u2026).`
170
+ );
171
+ }
172
+ if ("walletClient" in wallet) {
173
+ throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
174
+ `chain ${network} is NEAR; a viem { walletClient } can't be used \u2014 pass { accountId, privateKey }.`
175
+ );
176
+ }
177
+ if ("secretKey" in wallet || "signer" in wallet || "mnemonic" in wallet || "keyPair" in wallet || "secret" in wallet || "seed" in wallet || "keypair" in wallet) {
178
+ throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
179
+ `chain ${network} is NEAR; that looks like another family's wallet \u2014 pass { accountId, privateKey }.`
180
+ );
181
+ }
182
+ if (!("accountId" in wallet) || !("privateKey" in wallet)) {
183
+ throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
184
+ `chain ${network} is NEAR; wallet must be { accountId, privateKey } (privateKey = ed25519:\u2026).`
185
+ );
186
+ }
187
+ return wallet;
188
+ }
189
+ function resolveNearWallet(config) {
190
+ if (!config.accountId || !config.privateKey) {
191
+ throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)("NEAR wallet needs { accountId, privateKey } (privateKey = ed25519:\u2026).");
192
+ }
193
+ let signer;
194
+ try {
195
+ signer = _nearapijs.KeyPairSigner.fromSecretKey(config.privateKey);
196
+ } catch (cause) {
197
+ throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)("NEAR wallet { privateKey } is not a valid ed25519:\u2026 secret key.", {
198
+ cause
199
+ });
200
+ }
201
+ return { accountId: config.accountId, signer };
202
+ }
203
+
204
+ // src/drivers/near/index.ts
205
+ var nearDriver = {
206
+ family: "near",
207
+ resolve(opts) {
208
+ if (opts.chain !== "near") return null;
209
+ const rpcUrl = _nullishCoalesce(opts.rpcUrl, () => ( NEAR_MAINNET.defaultRpc));
210
+ return makeNearNetwork(NEAR_MAINNET, rpcUrl);
211
+ }
212
+ };
213
+ function isValidNearAccountId(id) {
214
+ if (id.startsWith("0x")) return false;
215
+ if (id.length < 2 || id.length > 64) return false;
216
+ return /^(([a-z\d]+[-_])*[a-z\d]+\.)*([a-z\d]+[-_])*[a-z\d]+$/.test(id);
217
+ }
218
+ function makeNearNetwork(preset, rpcUrl) {
219
+ const provider = new (0, _nearapijs.JsonRpcProvider)({ url: rpcUrl });
220
+ const network = preset.caip2;
221
+ const reader = {
222
+ async txStatus(hash, senderId) {
223
+ const outcome = await provider.viewTransactionStatusWithReceipts({
224
+ txHash: hash,
225
+ accountId: senderId,
226
+ waitUntil: "EXECUTED_OPTIMISTIC"
227
+ });
228
+ if (!outcome) return null;
229
+ const status = outcome.status;
230
+ const success = typeof status === "object" && status !== null && "SuccessValue" in status;
231
+ const receipts = (_nullishCoalesce(outcome.receipts_outcome, () => ( []))).map((r) => ({
232
+ executorId: r.outcome.executor_id,
233
+ logs: _nullishCoalesce(r.outcome.logs, () => ( []))
234
+ }));
235
+ return { success, receipts };
236
+ }
237
+ };
238
+ return {
239
+ family: "near",
240
+ network,
241
+ supports: (n) => n === network,
242
+ resolveToken(token) {
243
+ if (token === "native") {
244
+ throw new (0, _chunkWQWNPAYQcjs.UnknownTokenError)(
245
+ `NEAR payments are NEP-141 token only \u2014 native NEAR isn't a built-in payment asset (a native transfer carries no memo to bind the payment). Use 'USDC' / 'USDT' or a custom { contractId, decimals }.`
246
+ );
247
+ }
248
+ if (typeof token === "string") {
249
+ const info = preset.tokens[token.toUpperCase()];
250
+ if (!info) {
251
+ const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
252
+ throw new (0, _chunkWQWNPAYQcjs.UnknownTokenError)(
253
+ `token "${token}" isn't built in for NEAR (known: ${known}). Pass { contractId, decimals } for a custom NEP-141.`
254
+ );
255
+ }
256
+ return { asset: info.contractId, decimals: info.decimals, symbol: info.symbol };
257
+ }
258
+ _chunkWQWNPAYQcjs.rejectForeignToken.call(void 0, token, "near", network);
259
+ const t = token;
260
+ if (!t.contractId || typeof t.decimals !== "number") {
261
+ throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
262
+ `chain ${network} is NEAR; a custom token must be { contractId, decimals }.`
263
+ );
264
+ }
265
+ return {
266
+ asset: t.contractId,
267
+ decimals: t.decimals,
268
+ ...t.symbol ? { symbol: t.symbol } : {}
269
+ };
270
+ },
271
+ describeAsset(asset) {
272
+ if (asset === "native") return null;
273
+ for (const info of Object.values(preset.tokens)) {
274
+ if (info.contractId === asset) return { symbol: info.symbol, decimals: info.decimals };
275
+ }
276
+ return null;
277
+ },
278
+ assertValidPayTo(payTo) {
279
+ if (payTo.startsWith("0x")) {
280
+ throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
281
+ `chain ${network} is NEAR, but payTo "${payTo}" looks like an EVM/Sui 0x address.`
282
+ );
283
+ }
284
+ if (!isValidNearAccountId(payTo)) {
285
+ throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
286
+ `chain ${network} is NEAR, but payTo "${payTo}" is not a valid NEAR account id.`
287
+ );
288
+ }
289
+ },
290
+ bindWallet(wallet) {
291
+ return { _native: assertNearWallet(wallet, network) };
292
+ },
293
+ async send(wallet, accept) {
294
+ const { accountId, signer } = resolveNearWallet(wallet._native);
295
+ const account = new (0, _nearapijs.Account)(accountId, provider, signer);
296
+ const client = {
297
+ async ftTransfer({ contractId, receiverId, amount, memo, gas, deposit }) {
298
+ const outcome = await account.signAndSendTransaction({
299
+ receiverId: contractId,
300
+ actions: [
301
+ _nearapijs.actions.functionCall("ft_transfer", { receiver_id: receiverId, amount, memo }, gas, deposit)
302
+ ]
303
+ });
304
+ const hash2 = _optionalChain([outcome, 'access', _ => _.transaction, 'optionalAccess', _2 => _2.hash]);
305
+ if (!hash2) throw new Error("NEAR: signAndSendTransaction returned no tx hash.");
306
+ return { hash: hash2 };
307
+ }
308
+ };
309
+ const hash = await payNear({ client, accept });
310
+ return encodeRef(accountId, hash);
311
+ },
312
+ async confirm(ref) {
313
+ const { senderId, hash } = decodeRef(ref);
314
+ try {
315
+ const tx = await reader.txStatus(hash, senderId);
316
+ if (tx && tx.success) return { height: "0" };
317
+ } catch (e4) {
318
+ }
319
+ throw new (0, _chunkWQWNPAYQcjs.ConfirmationTimeoutError)(`NEAR tx ${hash} not confirmed in time.`);
320
+ },
321
+ async estimateCost() {
322
+ return _chunkWQWNPAYQcjs.nativeCost.call(void 0, {
323
+ symbol: "NEAR",
324
+ decimals: NEAR_DECIMALS,
325
+ fee: 1500000000000000000000n,
326
+ basis: "heuristic",
327
+ detail: "~14 TGas for ft_transfer (\u22480.0015 NEAR) + 1 yoctoNEAR deposit"
328
+ });
329
+ },
330
+ async verify(ref, accept) {
331
+ const { senderId, hash } = decodeRef(ref);
332
+ return verifyNear({ reader, hash, senderId, accept });
333
+ }
334
+ };
335
+ }
336
+ function encodeRef(accountId, hash) {
337
+ return `${accountId}:${hash}`;
338
+ }
339
+ function decodeRef(ref) {
340
+ const i = ref.indexOf(":");
341
+ if (i < 0) return { senderId: "", hash: ref };
342
+ return { senderId: ref.slice(0, i), hash: ref.slice(i + 1) };
343
+ }
344
+
345
+
346
+ exports.nearDriver = nearDriver;
@@ -0,0 +1,346 @@
1
+ import {
2
+ ConfirmationTimeoutError,
3
+ InsufficientFundsError,
4
+ UnknownTokenError,
5
+ WrongFamilyError,
6
+ nativeCost,
7
+ rejectForeignToken,
8
+ toInsufficientFundsError
9
+ } from "./chunk-3TQJJ4SQ.js";
10
+
11
+ // src/drivers/near/index.ts
12
+ import { JsonRpcProvider, Account, actions } from "near-api-js";
13
+
14
+ // src/drivers/near/chains.ts
15
+ var NEAR_DECIMALS = 24;
16
+ var NEAR_MAINNET = {
17
+ caip2: "near:mainnet",
18
+ defaultRpc: "https://free.rpc.fastnear.com",
19
+ tokens: {
20
+ // Circle USDC — native (NOT the .factory.bridge.near bridge). Contract + 6dp
21
+ // verified live via ft_metadata before shipping.
22
+ USDC: {
23
+ contractId: "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1",
24
+ decimals: 6,
25
+ symbol: "USDC"
26
+ },
27
+ // Tether USDt — native (Tether's official tether-token.near account). On-chain
28
+ // symbol is "USDt"; contract + 6dp verified live via ft_metadata before shipping.
29
+ USDT: {
30
+ contractId: "usdt.tether-token.near",
31
+ decimals: 6,
32
+ symbol: "USDT"
33
+ }
34
+ }
35
+ };
36
+
37
+ // src/drivers/near/pay.ts
38
+ var FT_TRANSFER_GAS = 30000000000000n;
39
+ var ONE_YOCTO = 1n;
40
+ async function payNear(params) {
41
+ const { client, accept, gas } = params;
42
+ try {
43
+ const res = await client.ftTransfer({
44
+ contractId: accept.asset,
45
+ receiverId: accept.payTo,
46
+ amount: accept.amount,
47
+ memo: accept.extra.nonce,
48
+ // nonce binding (Template A)
49
+ gas: gas ?? FT_TRANSFER_GAS,
50
+ deposit: ONE_YOCTO
51
+ });
52
+ return res.hash;
53
+ } catch (err) {
54
+ if (isNearRegistrationError(err)) {
55
+ throw new Error(
56
+ `NEAR ft_transfer failed: recipient ${accept.payTo} isn't registered on token ${accept.asset} (NEP-145 storage_deposit). Register it once (\u22480.00125 NEAR) before it can receive.`,
57
+ { cause: err }
58
+ );
59
+ }
60
+ if (isNearAffordability(err)) {
61
+ throw new InsufficientFundsError(
62
+ err instanceof Error ? err.message : "Insufficient NEAR balance for the payment.",
63
+ { cause: err }
64
+ );
65
+ }
66
+ throw toInsufficientFundsError(err) ?? err;
67
+ }
68
+ }
69
+ function isNearRegistrationError(err) {
70
+ const m = err instanceof Error ? err.message : String(err);
71
+ return /not registered|storage_?deposit|The account .* is not registered/i.test(m);
72
+ }
73
+ function isNearAffordability(err) {
74
+ const m = err instanceof Error ? err.message : String(err);
75
+ return /not enough|doesn't have enough|does not have enough|lack ?balance|exceeds .*balance|insufficient/i.test(m);
76
+ }
77
+
78
+ // src/drivers/near/verify.ts
79
+ function parseFtTransferEvent(line) {
80
+ const marker = "EVENT_JSON:";
81
+ const i = line.indexOf(marker);
82
+ if (i < 0) return null;
83
+ try {
84
+ const ev = JSON.parse(line.slice(i + marker.length));
85
+ if (ev.standard === "nep141" && ev.event === "ft_transfer" && Array.isArray(ev.data)) {
86
+ return ev.data;
87
+ }
88
+ } catch {
89
+ }
90
+ return null;
91
+ }
92
+ async function verifyNear(params) {
93
+ const { reader, hash, senderId, accept } = params;
94
+ const required = BigInt(accept.amount);
95
+ const nonce = accept.extra.nonce;
96
+ let tx;
97
+ try {
98
+ tx = await reader.txStatus(hash, senderId);
99
+ } catch {
100
+ return txNotFound(hash);
101
+ }
102
+ if (!tx) return txNotFound(hash);
103
+ if (!tx.success) {
104
+ return { ok: false, error: "tx_reverted", detail: `NEAR tx ${hash} failed on-chain.` };
105
+ }
106
+ if (typeof tx.timestampMs === "number") {
107
+ const ageSeconds = Math.floor(Date.now() / 1e3) - Math.floor(tx.timestampMs / 1e3);
108
+ if (ageSeconds > accept.maxTimeoutSeconds) {
109
+ return {
110
+ ok: false,
111
+ error: "payment_expired",
112
+ detail: `Payment is ${ageSeconds}s old; max allowed is ${accept.maxTimeoutSeconds}s.`
113
+ };
114
+ }
115
+ }
116
+ let paid = 0n;
117
+ let payer = "";
118
+ for (const r of tx.receipts) {
119
+ if (r.executorId !== accept.asset) continue;
120
+ for (const line of r.logs) {
121
+ const data = parseFtTransferEvent(line);
122
+ if (!data) continue;
123
+ for (const d of data) {
124
+ if (d.new_owner_id === accept.payTo && (d.memo ?? "") === nonce) {
125
+ try {
126
+ paid += BigInt(d.amount ?? "0");
127
+ } catch {
128
+ }
129
+ if (!payer) payer = d.old_owner_id ?? "";
130
+ }
131
+ }
132
+ }
133
+ }
134
+ if (paid < required) {
135
+ return {
136
+ ok: false,
137
+ error: "transfer_not_found",
138
+ detail: `No NEP-141 ft_transfer of >= ${required} (token ${accept.asset}) to ${accept.payTo} carrying our nonce in ${hash}.`
139
+ };
140
+ }
141
+ return {
142
+ ok: true,
143
+ receipt: {
144
+ scheme: "onchain-proof",
145
+ success: true,
146
+ network: accept.network,
147
+ transaction: hash,
148
+ asset: accept.asset,
149
+ amount: accept.amount,
150
+ payer,
151
+ payTo: accept.payTo,
152
+ verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
153
+ }
154
+ };
155
+ }
156
+ function txNotFound(hash) {
157
+ return {
158
+ ok: false,
159
+ error: "tx_not_found",
160
+ detail: `NEAR tx ${hash} not found or not yet executed \u2014 retry.`
161
+ };
162
+ }
163
+
164
+ // src/drivers/near/wallet.ts
165
+ import { KeyPairSigner } from "near-api-js";
166
+ function assertNearWallet(wallet, network) {
167
+ if (typeof wallet !== "object" || wallet === null) {
168
+ throw new WrongFamilyError(
169
+ `chain ${network} is NEAR; wallet must be { accountId, privateKey } (privateKey = ed25519:\u2026).`
170
+ );
171
+ }
172
+ if ("walletClient" in wallet) {
173
+ throw new WrongFamilyError(
174
+ `chain ${network} is NEAR; a viem { walletClient } can't be used \u2014 pass { accountId, privateKey }.`
175
+ );
176
+ }
177
+ if ("secretKey" in wallet || "signer" in wallet || "mnemonic" in wallet || "keyPair" in wallet || "secret" in wallet || "seed" in wallet || "keypair" in wallet) {
178
+ throw new WrongFamilyError(
179
+ `chain ${network} is NEAR; that looks like another family's wallet \u2014 pass { accountId, privateKey }.`
180
+ );
181
+ }
182
+ if (!("accountId" in wallet) || !("privateKey" in wallet)) {
183
+ throw new WrongFamilyError(
184
+ `chain ${network} is NEAR; wallet must be { accountId, privateKey } (privateKey = ed25519:\u2026).`
185
+ );
186
+ }
187
+ return wallet;
188
+ }
189
+ function resolveNearWallet(config) {
190
+ if (!config.accountId || !config.privateKey) {
191
+ throw new WrongFamilyError("NEAR wallet needs { accountId, privateKey } (privateKey = ed25519:\u2026).");
192
+ }
193
+ let signer;
194
+ try {
195
+ signer = KeyPairSigner.fromSecretKey(config.privateKey);
196
+ } catch (cause) {
197
+ throw new WrongFamilyError("NEAR wallet { privateKey } is not a valid ed25519:\u2026 secret key.", {
198
+ cause
199
+ });
200
+ }
201
+ return { accountId: config.accountId, signer };
202
+ }
203
+
204
+ // src/drivers/near/index.ts
205
+ var nearDriver = {
206
+ family: "near",
207
+ resolve(opts) {
208
+ if (opts.chain !== "near") return null;
209
+ const rpcUrl = opts.rpcUrl ?? NEAR_MAINNET.defaultRpc;
210
+ return makeNearNetwork(NEAR_MAINNET, rpcUrl);
211
+ }
212
+ };
213
+ function isValidNearAccountId(id) {
214
+ if (id.startsWith("0x")) return false;
215
+ if (id.length < 2 || id.length > 64) return false;
216
+ return /^(([a-z\d]+[-_])*[a-z\d]+\.)*([a-z\d]+[-_])*[a-z\d]+$/.test(id);
217
+ }
218
+ function makeNearNetwork(preset, rpcUrl) {
219
+ const provider = new JsonRpcProvider({ url: rpcUrl });
220
+ const network = preset.caip2;
221
+ const reader = {
222
+ async txStatus(hash, senderId) {
223
+ const outcome = await provider.viewTransactionStatusWithReceipts({
224
+ txHash: hash,
225
+ accountId: senderId,
226
+ waitUntil: "EXECUTED_OPTIMISTIC"
227
+ });
228
+ if (!outcome) return null;
229
+ const status = outcome.status;
230
+ const success = typeof status === "object" && status !== null && "SuccessValue" in status;
231
+ const receipts = (outcome.receipts_outcome ?? []).map((r) => ({
232
+ executorId: r.outcome.executor_id,
233
+ logs: r.outcome.logs ?? []
234
+ }));
235
+ return { success, receipts };
236
+ }
237
+ };
238
+ return {
239
+ family: "near",
240
+ network,
241
+ supports: (n) => n === network,
242
+ resolveToken(token) {
243
+ if (token === "native") {
244
+ throw new UnknownTokenError(
245
+ `NEAR payments are NEP-141 token only \u2014 native NEAR isn't a built-in payment asset (a native transfer carries no memo to bind the payment). Use 'USDC' / 'USDT' or a custom { contractId, decimals }.`
246
+ );
247
+ }
248
+ if (typeof token === "string") {
249
+ const info = preset.tokens[token.toUpperCase()];
250
+ if (!info) {
251
+ const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
252
+ throw new UnknownTokenError(
253
+ `token "${token}" isn't built in for NEAR (known: ${known}). Pass { contractId, decimals } for a custom NEP-141.`
254
+ );
255
+ }
256
+ return { asset: info.contractId, decimals: info.decimals, symbol: info.symbol };
257
+ }
258
+ rejectForeignToken(token, "near", network);
259
+ const t = token;
260
+ if (!t.contractId || typeof t.decimals !== "number") {
261
+ throw new WrongFamilyError(
262
+ `chain ${network} is NEAR; a custom token must be { contractId, decimals }.`
263
+ );
264
+ }
265
+ return {
266
+ asset: t.contractId,
267
+ decimals: t.decimals,
268
+ ...t.symbol ? { symbol: t.symbol } : {}
269
+ };
270
+ },
271
+ describeAsset(asset) {
272
+ if (asset === "native") return null;
273
+ for (const info of Object.values(preset.tokens)) {
274
+ if (info.contractId === asset) return { symbol: info.symbol, decimals: info.decimals };
275
+ }
276
+ return null;
277
+ },
278
+ assertValidPayTo(payTo) {
279
+ if (payTo.startsWith("0x")) {
280
+ throw new WrongFamilyError(
281
+ `chain ${network} is NEAR, but payTo "${payTo}" looks like an EVM/Sui 0x address.`
282
+ );
283
+ }
284
+ if (!isValidNearAccountId(payTo)) {
285
+ throw new WrongFamilyError(
286
+ `chain ${network} is NEAR, but payTo "${payTo}" is not a valid NEAR account id.`
287
+ );
288
+ }
289
+ },
290
+ bindWallet(wallet) {
291
+ return { _native: assertNearWallet(wallet, network) };
292
+ },
293
+ async send(wallet, accept) {
294
+ const { accountId, signer } = resolveNearWallet(wallet._native);
295
+ const account = new Account(accountId, provider, signer);
296
+ const client = {
297
+ async ftTransfer({ contractId, receiverId, amount, memo, gas, deposit }) {
298
+ const outcome = await account.signAndSendTransaction({
299
+ receiverId: contractId,
300
+ actions: [
301
+ actions.functionCall("ft_transfer", { receiver_id: receiverId, amount, memo }, gas, deposit)
302
+ ]
303
+ });
304
+ const hash2 = outcome.transaction?.hash;
305
+ if (!hash2) throw new Error("NEAR: signAndSendTransaction returned no tx hash.");
306
+ return { hash: hash2 };
307
+ }
308
+ };
309
+ const hash = await payNear({ client, accept });
310
+ return encodeRef(accountId, hash);
311
+ },
312
+ async confirm(ref) {
313
+ const { senderId, hash } = decodeRef(ref);
314
+ try {
315
+ const tx = await reader.txStatus(hash, senderId);
316
+ if (tx && tx.success) return { height: "0" };
317
+ } catch {
318
+ }
319
+ throw new ConfirmationTimeoutError(`NEAR tx ${hash} not confirmed in time.`);
320
+ },
321
+ async estimateCost() {
322
+ return nativeCost({
323
+ symbol: "NEAR",
324
+ decimals: NEAR_DECIMALS,
325
+ fee: 1500000000000000000000n,
326
+ basis: "heuristic",
327
+ detail: "~14 TGas for ft_transfer (\u22480.0015 NEAR) + 1 yoctoNEAR deposit"
328
+ });
329
+ },
330
+ async verify(ref, accept) {
331
+ const { senderId, hash } = decodeRef(ref);
332
+ return verifyNear({ reader, hash, senderId, accept });
333
+ }
334
+ };
335
+ }
336
+ function encodeRef(accountId, hash) {
337
+ return `${accountId}:${hash}`;
338
+ }
339
+ function decodeRef(ref) {
340
+ const i = ref.indexOf(":");
341
+ if (i < 0) return { senderId: "", hash: ref };
342
+ return { senderId: ref.slice(0, i), hash: ref.slice(i + 1) };
343
+ }
344
+ export {
345
+ nearDriver
346
+ };