@fastnear/intents 1.6.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 +249 -0
- package/dist/cjs/index.cjs +524 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.d.cts +209 -0
- package/dist/cjs/node.cjs +188 -0
- package/dist/cjs/node.cjs.map +1 -0
- package/dist/cjs/node.d.cts +21 -0
- package/dist/cjs/relay.cjs +127 -0
- package/dist/cjs/relay.cjs.map +1 -0
- package/dist/cjs/relay.d.cts +40 -0
- package/dist/cjs/types-BQpqppU6.d.cts +343 -0
- package/dist/esm/index.d.ts +209 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/node.d.ts +21 -0
- package/dist/esm/node.js +76 -0
- package/dist/esm/node.js.map +1 -0
- package/dist/esm/one-click.js +84 -0
- package/dist/esm/one-click.js.map +1 -0
- package/dist/esm/relay.d.ts +40 -0
- package/dist/esm/relay.js +85 -0
- package/dist/esm/relay.js.map +1 -0
- package/dist/esm/signing.js +198 -0
- package/dist/esm/signing.js.map +1 -0
- package/dist/esm/types-BQpqppU6.d.ts +343 -0
- package/dist/esm/types.js +11 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/verifier.js +124 -0
- package/dist/esm/verifier.js.map +1 -0
- package/dist/umd/browser.global.js +802 -0
- package/dist/umd/browser.global.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/* ⋈ 🏃🏻💨 FastNear intents - CJS (@fastnear/intents version 1.6.0) */
|
|
2
|
+
/* https://www.npmjs.com/package/@fastnear/intents/v/1.6.0 */
|
|
3
|
+
"use strict";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
|
+
|
|
23
|
+
// src/index.ts
|
|
24
|
+
var src_exports = {};
|
|
25
|
+
__export(src_exports, {
|
|
26
|
+
FT_TRANSFER_CALL_GAS: () => FT_TRANSFER_CALL_GAS,
|
|
27
|
+
INTENTS_CONTRACT_ID: () => INTENTS_CONTRACT_ID,
|
|
28
|
+
IntentsHttpError: () => IntentsHttpError,
|
|
29
|
+
ONE_CLICK_BASE_URL: () => ONE_CLICK_BASE_URL,
|
|
30
|
+
ONE_YOCTO: () => ONE_YOCTO,
|
|
31
|
+
SOLVER_RELAY_URL: () => SOLVER_RELAY_URL,
|
|
32
|
+
SolverRelayError: () => SolverRelayError,
|
|
33
|
+
WITHDRAW_GAS: () => WITHDRAW_GAS,
|
|
34
|
+
WRAP_NEAR_CONTRACT_ID: () => WRAP_NEAR_CONTRACT_ID,
|
|
35
|
+
WRAP_NEAR_GAS: () => WRAP_NEAR_GAS,
|
|
36
|
+
buildIntentMessage: () => buildIntentMessage,
|
|
37
|
+
createOneClickClient: () => createOneClickClient,
|
|
38
|
+
createSolverRelayClient: () => createSolverRelayClient,
|
|
39
|
+
createWalletIntentSigner: () => createWalletIntentSigner,
|
|
40
|
+
defaultDeadline: () => defaultDeadline,
|
|
41
|
+
encodeIntentSignature: () => encodeIntentSignature,
|
|
42
|
+
ftDepositAction: () => ftDepositAction,
|
|
43
|
+
ftWithdrawAction: () => ftWithdrawAction,
|
|
44
|
+
mtBalance: () => mtBalance,
|
|
45
|
+
mtBatchBalances: () => mtBatchBalances,
|
|
46
|
+
normalizeIntentPublicKey: () => normalizeIntentPublicKey,
|
|
47
|
+
randomNonce: () => randomNonce,
|
|
48
|
+
toSignedIntent: () => toSignedIntent,
|
|
49
|
+
unsignedPayloadParts: () => unsignedPayloadParts,
|
|
50
|
+
wrapNearAction: () => wrapNearAction
|
|
51
|
+
});
|
|
52
|
+
module.exports = __toCommonJS(src_exports);
|
|
53
|
+
|
|
54
|
+
// src/types.ts
|
|
55
|
+
var INTENTS_CONTRACT_ID = "intents.near";
|
|
56
|
+
var ONE_CLICK_BASE_URL = "https://1click.chaindefuser.com";
|
|
57
|
+
var SOLVER_RELAY_URL = "https://solver-relay-v2.chaindefuser.com/rpc";
|
|
58
|
+
|
|
59
|
+
// src/one-click.ts
|
|
60
|
+
var IntentsHttpError = class extends Error {
|
|
61
|
+
static {
|
|
62
|
+
__name(this, "IntentsHttpError");
|
|
63
|
+
}
|
|
64
|
+
status;
|
|
65
|
+
body;
|
|
66
|
+
constructor(message, status, body) {
|
|
67
|
+
super(message);
|
|
68
|
+
this.name = "IntentsHttpError";
|
|
69
|
+
this.status = status;
|
|
70
|
+
this.body = body;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
async function parseBody(response) {
|
|
74
|
+
const text = await response.text();
|
|
75
|
+
try {
|
|
76
|
+
return text ? JSON.parse(text) : null;
|
|
77
|
+
} catch {
|
|
78
|
+
return text;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
__name(parseBody, "parseBody");
|
|
82
|
+
function createOneClickClient(options = {}) {
|
|
83
|
+
const baseUrl = (options.baseUrl ?? ONE_CLICK_BASE_URL).replace(/\/$/, "");
|
|
84
|
+
const fetchImplementation = options.fetch ?? globalThis.fetch;
|
|
85
|
+
if (typeof fetchImplementation !== "function") {
|
|
86
|
+
throw new Error("A fetch implementation is required");
|
|
87
|
+
}
|
|
88
|
+
const authHeaders = {};
|
|
89
|
+
if (options.apiKey) authHeaders["X-API-Key"] = options.apiKey;
|
|
90
|
+
if (options.jwt) authHeaders.Authorization = `Bearer ${options.jwt}`;
|
|
91
|
+
async function request(method, path, body) {
|
|
92
|
+
const headers = body === void 0 ? authHeaders : { ...authHeaders, "Content-Type": "application/json" };
|
|
93
|
+
const response = await fetchImplementation(`${baseUrl}${path}`, {
|
|
94
|
+
method,
|
|
95
|
+
headers,
|
|
96
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) }
|
|
97
|
+
});
|
|
98
|
+
const parsed = await parseBody(response);
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
const detail = parsed && typeof parsed === "object" && "message" in parsed ? ` \u2014 ${JSON.stringify(parsed.message)}` : "";
|
|
101
|
+
throw new IntentsHttpError(
|
|
102
|
+
`1Click ${method} ${path} failed with ${response.status}${detail}`,
|
|
103
|
+
response.status,
|
|
104
|
+
parsed
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return parsed;
|
|
108
|
+
}
|
|
109
|
+
__name(request, "request");
|
|
110
|
+
return {
|
|
111
|
+
tokens: /* @__PURE__ */ __name(() => request("GET", "/v0/tokens"), "tokens"),
|
|
112
|
+
quote: /* @__PURE__ */ __name((quoteRequest) => request("POST", "/v0/quote", quoteRequest), "quote"),
|
|
113
|
+
status: /* @__PURE__ */ __name(({ depositAddress, depositMemo }) => {
|
|
114
|
+
const query = new URLSearchParams({ depositAddress });
|
|
115
|
+
if (depositMemo) query.set("depositMemo", depositMemo);
|
|
116
|
+
return request("GET", `/v0/status?${query}`);
|
|
117
|
+
}, "status"),
|
|
118
|
+
submitDeposit: /* @__PURE__ */ __name((submitRequest) => request("POST", "/v0/deposit/submit", submitRequest), "submitDeposit"),
|
|
119
|
+
generateIntent: /* @__PURE__ */ __name(({ standard = "nep413", signerId, depositAddress }) => request("POST", "/v0/generate-intent", {
|
|
120
|
+
type: "swap_transfer",
|
|
121
|
+
standard,
|
|
122
|
+
signerId,
|
|
123
|
+
depositAddress
|
|
124
|
+
}), "generateIntent"),
|
|
125
|
+
submitIntent: /* @__PURE__ */ __name(({ signedData }) => request("POST", "/v0/submit-intent", {
|
|
126
|
+
type: "swap_transfer",
|
|
127
|
+
signedData
|
|
128
|
+
}), "submitIntent")
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
__name(createOneClickClient, "createOneClickClient");
|
|
132
|
+
|
|
133
|
+
// src/signing.ts
|
|
134
|
+
var import_utils = require("@fastnear/utils");
|
|
135
|
+
function randomNonce() {
|
|
136
|
+
return crypto.getRandomValues(new Uint8Array(32));
|
|
137
|
+
}
|
|
138
|
+
__name(randomNonce, "randomNonce");
|
|
139
|
+
var DEFAULT_DEADLINE_MS = 5 * 60 * 1e3;
|
|
140
|
+
function defaultDeadline(ms = DEFAULT_DEADLINE_MS) {
|
|
141
|
+
return new Date(Date.now() + ms).toISOString();
|
|
142
|
+
}
|
|
143
|
+
__name(defaultDeadline, "defaultDeadline");
|
|
144
|
+
function buildIntentMessage({
|
|
145
|
+
signerId,
|
|
146
|
+
intents,
|
|
147
|
+
deadline
|
|
148
|
+
}) {
|
|
149
|
+
if (!signerId) throw new Error("signerId is required");
|
|
150
|
+
if (!Array.isArray(intents) || intents.length === 0) {
|
|
151
|
+
throw new Error("At least one intent is required");
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
signer_id: signerId,
|
|
155
|
+
deadline: deadline ?? defaultDeadline(),
|
|
156
|
+
intents
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
__name(buildIntentMessage, "buildIntentMessage");
|
|
160
|
+
function encodeIntentSignature(signature) {
|
|
161
|
+
if (typeof signature === "string") {
|
|
162
|
+
if (signature.startsWith("ed25519:") || signature.startsWith("secp256k1:")) {
|
|
163
|
+
return signature;
|
|
164
|
+
}
|
|
165
|
+
return encodeIntentSignature((0, import_utils.base64ToBytes)(signature));
|
|
166
|
+
}
|
|
167
|
+
if (signature.length === 64) return `ed25519:${(0, import_utils.toBase58)(signature)}`;
|
|
168
|
+
if (signature.length === 65) return `secp256k1:${(0, import_utils.toBase58)(signature)}`;
|
|
169
|
+
throw new Error(
|
|
170
|
+
`Unsupported NEP-413 signature length: ${signature.length} (expected 64 or 65 bytes)`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
__name(encodeIntentSignature, "encodeIntentSignature");
|
|
174
|
+
function normalizeIntentPublicKey(publicKey) {
|
|
175
|
+
if (!publicKey) throw new Error("A public key is required");
|
|
176
|
+
return publicKey.includes(":") ? publicKey : `ed25519:${publicKey}`;
|
|
177
|
+
}
|
|
178
|
+
__name(normalizeIntentPublicKey, "normalizeIntentPublicKey");
|
|
179
|
+
function toSignedIntent({
|
|
180
|
+
message,
|
|
181
|
+
nonce,
|
|
182
|
+
recipient = INTENTS_CONTRACT_ID,
|
|
183
|
+
publicKey,
|
|
184
|
+
signature,
|
|
185
|
+
callbackUrl
|
|
186
|
+
}) {
|
|
187
|
+
if (nonce.length !== 32) {
|
|
188
|
+
throw new Error(`NEP-413 nonce must be exactly 32 bytes, got ${nonce.length}`);
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
standard: "nep413",
|
|
192
|
+
payload: {
|
|
193
|
+
message: typeof message === "string" ? message : JSON.stringify(message),
|
|
194
|
+
nonce: (0, import_utils.bytesToBase64)(nonce),
|
|
195
|
+
recipient,
|
|
196
|
+
...callbackUrl ? { callbackUrl } : {}
|
|
197
|
+
},
|
|
198
|
+
public_key: normalizeIntentPublicKey(publicKey),
|
|
199
|
+
signature: encodeIntentSignature(signature)
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
__name(toSignedIntent, "toSignedIntent");
|
|
203
|
+
function unsignedPayloadParts(input) {
|
|
204
|
+
const payload = "payload" in input && typeof input.payload === "object" ? input.payload : input;
|
|
205
|
+
if ("standard" in input && typeof input.standard === "string" && input.standard !== "nep413") {
|
|
206
|
+
throw new Error(
|
|
207
|
+
`This signer only signs nep413 payloads; got standard "${input.standard}"`
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
if (typeof payload?.message !== "string" || typeof payload?.recipient !== "string") {
|
|
211
|
+
throw new Error("Unsigned payload must carry message and recipient strings");
|
|
212
|
+
}
|
|
213
|
+
const nonce = typeof payload.nonce === "string" ? (0, import_utils.base64ToBytes)(payload.nonce) : payload.nonce;
|
|
214
|
+
if (!(nonce instanceof Uint8Array) || nonce.length !== 32) {
|
|
215
|
+
throw new Error("Unsigned payload nonce must decode to exactly 32 bytes");
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
message: payload.message,
|
|
219
|
+
nonce,
|
|
220
|
+
recipient: payload.recipient,
|
|
221
|
+
...payload.callbackUrl ? { callbackUrl: payload.callbackUrl } : {}
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
__name(unsignedPayloadParts, "unsignedPayloadParts");
|
|
225
|
+
function assertExpectedRecipient(recipient, options) {
|
|
226
|
+
const expected = options?.expectedRecipient ?? INTENTS_CONTRACT_ID;
|
|
227
|
+
if (recipient !== expected) {
|
|
228
|
+
throw new Error(
|
|
229
|
+
`Refusing to sign a payload for recipient "${recipient}" \u2014 expected "${expected}". Pass { expectedRecipient } only when intentionally targeting a different verifier.`
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
__name(assertExpectedRecipient, "assertExpectedRecipient");
|
|
234
|
+
function signerIdFromMessage(message) {
|
|
235
|
+
try {
|
|
236
|
+
const parsed = JSON.parse(message);
|
|
237
|
+
return typeof parsed?.signer_id === "string" ? parsed.signer_id : void 0;
|
|
238
|
+
} catch {
|
|
239
|
+
return void 0;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
__name(signerIdFromMessage, "signerIdFromMessage");
|
|
243
|
+
function createWalletIntentSigner({
|
|
244
|
+
wallet,
|
|
245
|
+
network = "mainnet"
|
|
246
|
+
}) {
|
|
247
|
+
if (!wallet || typeof wallet.signMessage !== "function") {
|
|
248
|
+
throw new Error(
|
|
249
|
+
"A FastNEAR wallet module with signMessage is required (connect @fastnear/wallet first)"
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
async function signParts({
|
|
253
|
+
message,
|
|
254
|
+
nonce,
|
|
255
|
+
recipient,
|
|
256
|
+
callbackUrl,
|
|
257
|
+
expectedSigner
|
|
258
|
+
}) {
|
|
259
|
+
if (callbackUrl) {
|
|
260
|
+
throw new Error(
|
|
261
|
+
"Wallet intent signing cannot bind callbackUrl payloads; use the local signer or drop callbackUrl"
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
const signed = await wallet.signMessage({
|
|
265
|
+
message,
|
|
266
|
+
recipient,
|
|
267
|
+
nonce,
|
|
268
|
+
network
|
|
269
|
+
});
|
|
270
|
+
if (expectedSigner && signed.accountId && signed.accountId !== expectedSigner) {
|
|
271
|
+
throw new Error(
|
|
272
|
+
`Wallet signed as ${signed.accountId} but the intent names ${expectedSigner}; reconnect the intended account`
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
return toSignedIntent({
|
|
276
|
+
message,
|
|
277
|
+
nonce,
|
|
278
|
+
recipient,
|
|
279
|
+
publicKey: signed.publicKey,
|
|
280
|
+
signature: signed.signature,
|
|
281
|
+
callbackUrl
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
__name(signParts, "signParts");
|
|
285
|
+
return {
|
|
286
|
+
async signIntents(params) {
|
|
287
|
+
const signerId = params.signerId ?? (typeof wallet.accountId === "function" ? wallet.accountId({ network }) : null);
|
|
288
|
+
if (!signerId) {
|
|
289
|
+
throw new Error(`No wallet account connected on ${network}`);
|
|
290
|
+
}
|
|
291
|
+
const message = buildIntentMessage({
|
|
292
|
+
signerId,
|
|
293
|
+
intents: params.intents,
|
|
294
|
+
deadline: params.deadline
|
|
295
|
+
});
|
|
296
|
+
return signParts({
|
|
297
|
+
message: JSON.stringify(message),
|
|
298
|
+
nonce: params.nonce ?? randomNonce(),
|
|
299
|
+
recipient: params.verifyingContract ?? INTENTS_CONTRACT_ID,
|
|
300
|
+
expectedSigner: signerId
|
|
301
|
+
});
|
|
302
|
+
},
|
|
303
|
+
async signPayload(payload, options) {
|
|
304
|
+
const parts = unsignedPayloadParts(payload);
|
|
305
|
+
assertExpectedRecipient(parts.recipient, options);
|
|
306
|
+
return signParts({
|
|
307
|
+
...parts,
|
|
308
|
+
expectedSigner: signerIdFromMessage(parts.message)
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
__name(createWalletIntentSigner, "createWalletIntentSigner");
|
|
314
|
+
|
|
315
|
+
// src/verifier.ts
|
|
316
|
+
var FT_TRANSFER_CALL_GAS = "100000000000000";
|
|
317
|
+
var WITHDRAW_GAS = "100000000000000";
|
|
318
|
+
var WRAP_NEAR_GAS = "30000000000000";
|
|
319
|
+
var ONE_YOCTO = "1";
|
|
320
|
+
var WRAP_NEAR_CONTRACT_ID = "wrap.near";
|
|
321
|
+
function ftDepositAction({
|
|
322
|
+
amount,
|
|
323
|
+
creditTo,
|
|
324
|
+
msg,
|
|
325
|
+
verifierId = INTENTS_CONTRACT_ID,
|
|
326
|
+
gas = FT_TRANSFER_CALL_GAS
|
|
327
|
+
}) {
|
|
328
|
+
if (creditTo !== void 0 && msg !== void 0) {
|
|
329
|
+
throw new Error("Pass either creditTo or msg, not both");
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
type: "FunctionCall",
|
|
333
|
+
methodName: "ft_transfer_call",
|
|
334
|
+
args: {
|
|
335
|
+
receiver_id: verifierId,
|
|
336
|
+
amount,
|
|
337
|
+
msg: msg ?? creditTo ?? ""
|
|
338
|
+
},
|
|
339
|
+
gas,
|
|
340
|
+
deposit: ONE_YOCTO
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
__name(ftDepositAction, "ftDepositAction");
|
|
344
|
+
function wrapNearAction({
|
|
345
|
+
amountYocto,
|
|
346
|
+
gas = WRAP_NEAR_GAS
|
|
347
|
+
}) {
|
|
348
|
+
return {
|
|
349
|
+
type: "FunctionCall",
|
|
350
|
+
methodName: "near_deposit",
|
|
351
|
+
args: {},
|
|
352
|
+
gas,
|
|
353
|
+
deposit: amountYocto
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
__name(wrapNearAction, "wrapNearAction");
|
|
357
|
+
function ftWithdrawAction({
|
|
358
|
+
token,
|
|
359
|
+
receiverId,
|
|
360
|
+
amount,
|
|
361
|
+
memo,
|
|
362
|
+
msg,
|
|
363
|
+
storageDeposit,
|
|
364
|
+
gas = WITHDRAW_GAS
|
|
365
|
+
}) {
|
|
366
|
+
if (token.includes(":")) {
|
|
367
|
+
throw new Error(
|
|
368
|
+
`ft_withdraw takes the plain token contract id, not a prefixed multi-token id: ${token}`
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
return {
|
|
372
|
+
type: "FunctionCall",
|
|
373
|
+
methodName: "ft_withdraw",
|
|
374
|
+
args: {
|
|
375
|
+
token,
|
|
376
|
+
receiver_id: receiverId,
|
|
377
|
+
amount,
|
|
378
|
+
...memo !== void 0 ? { memo } : {},
|
|
379
|
+
...msg !== void 0 ? { msg } : {},
|
|
380
|
+
...storageDeposit !== void 0 ? { storage_deposit: storageDeposit } : {}
|
|
381
|
+
},
|
|
382
|
+
gas,
|
|
383
|
+
deposit: ONE_YOCTO
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
__name(ftWithdrawAction, "ftWithdrawAction");
|
|
387
|
+
async function mtBalance({
|
|
388
|
+
accountId,
|
|
389
|
+
tokenId,
|
|
390
|
+
view,
|
|
391
|
+
verifierId = INTENTS_CONTRACT_ID
|
|
392
|
+
}) {
|
|
393
|
+
const result = await view({
|
|
394
|
+
contractId: verifierId,
|
|
395
|
+
methodName: "mt_balance_of",
|
|
396
|
+
args: { account_id: accountId, token_id: tokenId }
|
|
397
|
+
});
|
|
398
|
+
return String(result ?? "0");
|
|
399
|
+
}
|
|
400
|
+
__name(mtBalance, "mtBalance");
|
|
401
|
+
async function mtBatchBalances({
|
|
402
|
+
accountId,
|
|
403
|
+
tokenIds,
|
|
404
|
+
view,
|
|
405
|
+
verifierId = INTENTS_CONTRACT_ID
|
|
406
|
+
}) {
|
|
407
|
+
const result = await view({
|
|
408
|
+
contractId: verifierId,
|
|
409
|
+
methodName: "mt_batch_balance_of",
|
|
410
|
+
args: { account_id: accountId, token_ids: tokenIds }
|
|
411
|
+
});
|
|
412
|
+
if (!Array.isArray(result) || result.length !== tokenIds.length) {
|
|
413
|
+
throw new Error(
|
|
414
|
+
`mt_batch_balance_of returned ${Array.isArray(result) ? result.length : typeof result} results for ${tokenIds.length} token ids`
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
return Object.fromEntries(
|
|
418
|
+
tokenIds.map((tokenId, index) => [tokenId, String(result[index] ?? "0")])
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
__name(mtBatchBalances, "mtBatchBalances");
|
|
422
|
+
|
|
423
|
+
// src/relay.ts
|
|
424
|
+
var SolverRelayError = class extends Error {
|
|
425
|
+
static {
|
|
426
|
+
__name(this, "SolverRelayError");
|
|
427
|
+
}
|
|
428
|
+
rpcError;
|
|
429
|
+
constructor(message, rpcError) {
|
|
430
|
+
super(message);
|
|
431
|
+
this.name = "SolverRelayError";
|
|
432
|
+
this.rpcError = rpcError;
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
function createSolverRelayClient(options = {}) {
|
|
436
|
+
const url = options.url ?? SOLVER_RELAY_URL;
|
|
437
|
+
const fetchImplementation = options.fetch ?? globalThis.fetch;
|
|
438
|
+
if (typeof fetchImplementation !== "function") {
|
|
439
|
+
throw new Error("A fetch implementation is required");
|
|
440
|
+
}
|
|
441
|
+
const headers = { "Content-Type": "application/json" };
|
|
442
|
+
if (options.apiKey) headers["X-API-Key"] = options.apiKey;
|
|
443
|
+
let nextId = 0;
|
|
444
|
+
async function call(method, params) {
|
|
445
|
+
const id = ++nextId;
|
|
446
|
+
const response = await fetchImplementation(url, {
|
|
447
|
+
method: "POST",
|
|
448
|
+
headers,
|
|
449
|
+
body: JSON.stringify({ id, jsonrpc: "2.0", method, params: [params] })
|
|
450
|
+
});
|
|
451
|
+
const text = await response.text();
|
|
452
|
+
let parsed = null;
|
|
453
|
+
try {
|
|
454
|
+
parsed = text ? JSON.parse(text) : null;
|
|
455
|
+
} catch {
|
|
456
|
+
parsed = text;
|
|
457
|
+
}
|
|
458
|
+
if (!response.ok) {
|
|
459
|
+
throw new IntentsHttpError(
|
|
460
|
+
`Solver relay ${method} failed with ${response.status}`,
|
|
461
|
+
response.status,
|
|
462
|
+
parsed
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
const body = parsed;
|
|
466
|
+
if (body && typeof body === "object" && body.error != null) {
|
|
467
|
+
throw new SolverRelayError(
|
|
468
|
+
`Solver relay ${method} returned an error: ${JSON.stringify(body.error)}`,
|
|
469
|
+
body.error
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
if (!body || typeof body !== "object" || !("result" in body)) {
|
|
473
|
+
throw new SolverRelayError(
|
|
474
|
+
`Solver relay ${method} returned a malformed JSON-RPC envelope`,
|
|
475
|
+
parsed
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
return body.result;
|
|
479
|
+
}
|
|
480
|
+
__name(call, "call");
|
|
481
|
+
return {
|
|
482
|
+
quote: /* @__PURE__ */ __name((params) => call("quote", params), "quote"),
|
|
483
|
+
publishIntent: /* @__PURE__ */ __name(({ signedData, quoteHashes }) => call("publish_intent", {
|
|
484
|
+
signed_data: signedData,
|
|
485
|
+
quote_hashes: quoteHashes
|
|
486
|
+
}), "publishIntent"),
|
|
487
|
+
publishIntents: /* @__PURE__ */ __name(({ signedDatas, quoteHashes, requote }) => call("publish_intents", {
|
|
488
|
+
signed_datas: signedDatas,
|
|
489
|
+
quote_hashes: quoteHashes,
|
|
490
|
+
...requote === void 0 ? {} : { requote }
|
|
491
|
+
}), "publishIntents"),
|
|
492
|
+
getStatus: /* @__PURE__ */ __name(({ intentHash }) => call("get_status", { intent_hash: intentHash }), "getStatus")
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
__name(createSolverRelayClient, "createSolverRelayClient");
|
|
496
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
497
|
+
0 && (module.exports = {
|
|
498
|
+
FT_TRANSFER_CALL_GAS,
|
|
499
|
+
INTENTS_CONTRACT_ID,
|
|
500
|
+
IntentsHttpError,
|
|
501
|
+
ONE_CLICK_BASE_URL,
|
|
502
|
+
ONE_YOCTO,
|
|
503
|
+
SOLVER_RELAY_URL,
|
|
504
|
+
SolverRelayError,
|
|
505
|
+
WITHDRAW_GAS,
|
|
506
|
+
WRAP_NEAR_CONTRACT_ID,
|
|
507
|
+
WRAP_NEAR_GAS,
|
|
508
|
+
buildIntentMessage,
|
|
509
|
+
createOneClickClient,
|
|
510
|
+
createSolverRelayClient,
|
|
511
|
+
createWalletIntentSigner,
|
|
512
|
+
defaultDeadline,
|
|
513
|
+
encodeIntentSignature,
|
|
514
|
+
ftDepositAction,
|
|
515
|
+
ftWithdrawAction,
|
|
516
|
+
mtBalance,
|
|
517
|
+
mtBatchBalances,
|
|
518
|
+
normalizeIntentPublicKey,
|
|
519
|
+
randomNonce,
|
|
520
|
+
toSignedIntent,
|
|
521
|
+
unsignedPayloadParts,
|
|
522
|
+
wrapNearAction
|
|
523
|
+
});
|
|
524
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/types.ts","../../src/one-click.ts","../../src/signing.ts","../../src/verifier.ts","../../src/relay.ts"],"sourcesContent":["/**\n * @fastnear/intents — NEAR Intents (intents.near) for end users and agents:\n * a zero-dependency 1Click swap client, NEP-413 intent signing (wallet and\n * local-key), verifier deposit/withdraw/balance helpers, and a solver-relay\n * JSON-RPC client.\n *\n * Browser-safe: this root entry never touches private keys. The local-key\n * signer lives in @fastnear/intents/node.\n */\nexport * from \"./types.js\";\nexport * from \"./one-click.js\";\nexport * from \"./signing.js\";\nexport * from \"./verifier.js\";\nexport * from \"./relay.js\";\n","/**\n * Protocol types for NEAR Intents (the verifier contract `intents.near`,\n * the 1Click swap API, and the solver relay).\n *\n * Sources of truth:\n * - 1Click OpenAPI: https://1click.chaindefuser.com/docs/v0/openapi.yaml\n * - Verifier docs: https://docs.near-intents.org/integration/verifier-contract\n * - Solver relay: https://docs.near-intents.org/integration/market-makers/message-bus/rpc.md\n */\n\n/** The NEAR Intents verifier contract (mainnet). */\nexport const INTENTS_CONTRACT_ID = \"intents.near\";\n\n/** Hosted 1Click swap API base URL. */\nexport const ONE_CLICK_BASE_URL = \"https://1click.chaindefuser.com\";\n\n/** Hosted solver relay JSON-RPC endpoint. */\nexport const SOLVER_RELAY_URL = \"https://solver-relay-v2.chaindefuser.com/rpc\";\n\n/**\n * A multi-token id inside the verifier's NEP-245 ledger:\n * `nep141:<contract>`, `nep171:<contract>:<token_id>`, or\n * `nep245:<contract>:<token_id>`.\n */\nexport type IntentsTokenId = string;\n\n// ---------------------------------------------------------------------------\n// Intent types executed by intents.near\n// ---------------------------------------------------------------------------\n\n/**\n * Trade intent: per-token balance deltas for the signer. Negative amounts are\n * paid by the signer, positive amounts are received. The verifier requires all\n * diffs in a batch to sum to zero per token, so a counterparty (solver) signs\n * the mirror diff.\n */\nexport interface TokenDiffIntent {\n intent: \"token_diff\";\n diff: Record<IntentsTokenId, string>;\n memo?: string;\n referral?: string;\n}\n\n/** Internal ledger transfer to another intents.near account. */\nexport interface TransferIntent {\n intent: \"transfer\";\n receiver_id: string;\n tokens: Record<IntentsTokenId, string>;\n memo?: string;\n}\n\n/**\n * Withdraw a NEP-141 token out of the verifier. `token` is the plain token\n * contract id (no `nep141:` prefix). Omit `msg` for refundable ft_transfer\n * semantics; passing `msg` switches to ft_transfer_call with no refund.\n */\nexport interface FtWithdrawIntent {\n intent: \"ft_withdraw\";\n token: string;\n receiver_id: string;\n amount: string;\n memo?: string;\n msg?: string;\n storage_deposit?: string;\n}\n\nexport interface NftWithdrawIntent {\n intent: \"nft_withdraw\";\n token: string;\n receiver_id: string;\n token_id: string;\n memo?: string;\n msg?: string;\n storage_deposit?: string;\n}\n\nexport interface MtWithdrawIntent {\n intent: \"mt_withdraw\";\n token: string;\n receiver_id: string;\n token_ids: string[];\n amounts: string[];\n memo?: string;\n msg?: string;\n storage_deposit?: string;\n}\n\n/** The only way to withdraw native NEAR: unwraps internal wNEAR on exit. */\nexport interface NativeWithdrawIntent {\n intent: \"native_withdraw\";\n receiver_id: string;\n amount: string;\n}\n\n/**\n * Pay a NEP-145 storage_deposit on a token contract from the signer's\n * internal wNEAR balance (registers a receiver before a withdrawal lands).\n */\nexport interface StorageDepositIntent {\n intent: \"storage_deposit\";\n contract_id: string;\n account_id: string;\n amount: string;\n}\n\nexport type Intent =\n | TokenDiffIntent\n | TransferIntent\n | FtWithdrawIntent\n | NftWithdrawIntent\n | MtWithdrawIntent\n | NativeWithdrawIntent\n | StorageDepositIntent;\n\n/**\n * The inner message that gets signed. For the `nep413` standard this JSON\n * string becomes the NEP-413 `message`, while the verifying contract and\n * replay nonce live in the NEP-413 envelope (`recipient` / `nonce`).\n */\nexport interface IntentMessage {\n signer_id: string;\n /** ISO-8601 timestamp after which the signed intent is invalid. */\n deadline: string;\n intents: Intent[];\n}\n\n// ---------------------------------------------------------------------------\n// Signed payloads (MultiPayload)\n// ---------------------------------------------------------------------------\n\n/**\n * A NEP-413-signed intent as `intents.near`, the solver relay, and 1Click\n * accept it. Note the encodings: `nonce` is base64 of 32 bytes, while\n * `signature` and `public_key` are `ed25519:<base58>` strings — NOT the\n * base64 signature NEAR wallets return.\n */\nexport interface SignedIntentNep413 {\n standard: \"nep413\";\n payload: {\n message: string;\n nonce: string;\n recipient: string;\n callbackUrl?: string;\n };\n public_key: string;\n signature: string;\n}\n\n/**\n * Any signed payload standard the verifier accepts. This package produces\n * `nep413`; the other variants (erc191, tip191, raw_ed25519, webauthn,\n * ton_connect, sep53) are documented pass-through shapes.\n */\nexport type SignedIntent =\n | SignedIntentNep413\n | { standard: string; [key: string]: unknown };\n\n/**\n * An unsigned NEP-413 payload, as returned by 1Click's generate-intent\n * endpoint (nonce is base64 of 32 bytes when it arrives as a string).\n */\nexport interface UnsignedNep413Payload {\n message: string;\n nonce: string | Uint8Array;\n recipient: string;\n callbackUrl?: string;\n}\n\n/**\n * What signPayload accepts: a bare unsigned payload or the\n * { standard, payload } wrapper 1Click's generate-intent returns.\n */\nexport type GeneratedUnsignedIntent =\n | UnsignedNep413Payload\n | { standard: string; payload: UnsignedNep413Payload };\n\nexport interface SignPayloadOptions {\n /**\n * The verifying contract the payload's recipient must equal. Defaults to\n * intents.near — a server response naming any other recipient throws\n * instead of being signed. Set explicitly to sign for a different\n * (e.g. staging) verifier deployment.\n */\n expectedRecipient?: string;\n}\n\n/** The signer surface shared by the wallet and local-key implementations. */\nexport interface IntentSigner {\n /** Build and sign an intent message this client composes itself. */\n signIntents(params: SignIntentsParams): Promise<SignedIntentNep413>;\n /**\n * Sign a pre-built NEP-413 payload verbatim — the 1Click generate-intent\n * flow, where the server chooses the message, nonce, and recipient. The\n * recipient is pinned to intents.near unless options.expectedRecipient\n * overrides it, so a malicious or buggy server cannot redirect the\n * signature to another contract.\n */\n signPayload(\n payload: GeneratedUnsignedIntent,\n options?: SignPayloadOptions,\n ): Promise<SignedIntentNep413>;\n}\n\nexport interface SignIntentsParams {\n intents: Intent[];\n /** Defaults to the connected wallet account / the local signer account. */\n signerId?: string;\n /** ISO-8601; defaults to 5 minutes from now. */\n deadline?: string;\n /** 32 bytes; defaults to crypto-random. */\n nonce?: Uint8Array;\n /** Defaults to intents.near. Override only for a different verifier deployment. */\n verifyingContract?: string;\n}\n\n// ---------------------------------------------------------------------------\n// 1Click API shapes (v0)\n// ---------------------------------------------------------------------------\n\nexport type OneClickSwapType =\n | \"EXACT_INPUT\"\n | \"EXACT_OUTPUT\"\n | \"FLEX_INPUT\"\n | \"ANY_INPUT\";\n\nexport type OneClickDepositType =\n | \"ORIGIN_CHAIN\"\n | \"INTENTS\"\n | \"CONFIDENTIAL_INTENTS\";\n\nexport type OneClickRecipientType =\n | \"DESTINATION_CHAIN\"\n | \"INTENTS\"\n | \"CONFIDENTIAL_INTENTS\";\n\nexport type OneClickDepositMode = \"SIMPLE\" | \"MEMO\";\n\nexport interface OneClickToken {\n assetId: string;\n decimals: number;\n blockchain: string;\n symbol: string;\n price?: number;\n priceUpdatedAt?: string;\n contractAddress?: string;\n coingeckoId?: string;\n}\n\nexport interface OneClickAppFee {\n /** intents.near account that collects the fee. */\n recipient: string;\n /** Basis points. */\n fee: number;\n}\n\nexport interface OneClickQuoteRequest {\n /** true = price preview only (no depositAddress); false commits the quote. */\n dry: boolean;\n swapType: OneClickSwapType;\n /** Basis points, e.g. 100 = 1%. */\n slippageTolerance: number;\n originAsset: string;\n destinationAsset: string;\n /** Base units of the exact side selected by swapType. */\n amount: string;\n depositType: OneClickDepositType;\n refundTo: string;\n refundType: OneClickDepositType;\n recipient: string;\n recipientType: OneClickRecipientType;\n /** ISO-8601. */\n deadline: string;\n depositMode?: OneClickDepositMode;\n referral?: string;\n quoteWaitingTimeMs?: number;\n appFees?: OneClickAppFee[];\n insured?: boolean;\n connectedWallets?: unknown[];\n sessionId?: string;\n virtualChainRecipient?: string;\n virtualChainRefundRecipient?: string;\n customRecipientMsg?: string;\n}\n\nexport interface OneClickQuote {\n depositAddress?: string;\n depositMemo?: string;\n chainDepositAddresses?: Array<{ chain: string; depositAddress?: string; memo?: string }>;\n amountIn: string;\n amountInFormatted?: string;\n amountInUsd?: string;\n minAmountIn?: string;\n amountOut: string;\n amountOutFormatted?: string;\n amountOutUsd?: string;\n minAmountOut?: string;\n deadline?: string;\n timeWhenInactive?: string;\n timeEstimate?: number;\n refundFee?: string;\n withdrawFee?: string;\n virtualChainRecipient?: string;\n virtualChainRefundRecipient?: string;\n customRecipientMsg?: string;\n}\n\nexport interface OneClickQuoteResponse {\n correlationId?: string;\n timestamp: string;\n /** Server-signed quote (verifiable per the 1Click docs). */\n signature: string;\n quoteRequest: OneClickQuoteRequest;\n quote: OneClickQuote;\n}\n\nexport type OneClickStatus =\n | \"KNOWN_DEPOSIT_TX\"\n | \"PENDING_DEPOSIT\"\n | \"INCOMPLETE_DEPOSIT\"\n | \"PROCESSING\"\n | \"SUCCESS\"\n | \"REFUNDED\"\n | \"FAILED\";\n\nexport interface OneClickStatusResponse {\n correlationId?: string;\n quoteResponse: OneClickQuoteResponse;\n status: OneClickStatus;\n updatedAt: string;\n swapDetails?: {\n intentHashes?: string[];\n nearTxHashes?: string[];\n originChainTxHashes?: Array<{ hash: string; explorerUrl?: string }>;\n destinationChainTxHashes?: Array<{ hash: string; explorerUrl?: string }>;\n amountIn?: string;\n amountInFormatted?: string;\n amountInUsd?: string;\n amountOut?: string;\n amountOutFormatted?: string;\n amountOutUsd?: string;\n slippage?: number;\n depositedAmount?: string;\n refundedAmount?: string;\n refundReason?: string;\n withdrawFee?: string;\n referral?: string;\n };\n}\n\nexport interface OneClickSubmitDepositRequest {\n txHash: string;\n depositAddress: string;\n nearSenderAccount?: string;\n memo?: string;\n}\n\nexport type OneClickSigningStandard =\n | \"nep413\"\n | \"erc191\"\n | \"raw_ed25519\"\n | \"webauthn\"\n | \"ton_connect\"\n | \"sep53\"\n | \"tip191\";\n\nexport interface OneClickGenerateIntentRequest {\n signerId: string;\n depositAddress: string;\n standard?: OneClickSigningStandard;\n}\n\nexport interface OneClickGenerateIntentResponse {\n /** Unsigned payload to sign — pass it to an IntentSigner's signPayload. */\n intent: GeneratedUnsignedIntent;\n correlationId?: string;\n}\n\nexport interface OneClickSubmitIntentResponse {\n intentHash: string;\n correlationId?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Solver relay JSON-RPC shapes\n// ---------------------------------------------------------------------------\n\nexport interface RelayQuoteParams {\n defuse_asset_identifier_in: IntentsTokenId;\n defuse_asset_identifier_out: IntentsTokenId;\n exact_amount_in?: string;\n exact_amount_out?: string;\n /** Milliseconds; relay default is 60000. */\n min_deadline_ms?: number;\n}\n\nexport interface RelayQuote {\n quote_hash: string;\n defuse_asset_identifier_in: IntentsTokenId;\n defuse_asset_identifier_out: IntentsTokenId;\n amount_in: string;\n amount_out: string;\n expiration_time: string;\n}\n\nexport type RelayIntentStatus =\n | \"PENDING\"\n | \"TX_BROADCASTED\"\n | \"SETTLED\"\n | \"NOT_FOUND_OR_NOT_VALID\";\n\nexport interface RelayPublishResult {\n status: string;\n intent_hash: string;\n}\n\nexport interface RelayStatusResult {\n intent_hash: string;\n status: RelayIntentStatus;\n status_details?: string;\n data?: { hash?: string };\n filled_amounts?: string[];\n}\n","import {\n ONE_CLICK_BASE_URL,\n type OneClickGenerateIntentRequest,\n type OneClickGenerateIntentResponse,\n type OneClickQuoteRequest,\n type OneClickQuoteResponse,\n type OneClickStatusResponse,\n type OneClickSubmitDepositRequest,\n type OneClickSubmitIntentResponse,\n type OneClickToken,\n type SignedIntent,\n} from \"./types.js\";\n\n/** Error thrown for non-2xx 1Click (and solver relay) HTTP responses. */\nexport class IntentsHttpError extends Error {\n readonly status: number;\n readonly body: unknown;\n\n constructor(message: string, status: number, body: unknown) {\n super(message);\n this.name = \"IntentsHttpError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport interface OneClickClientOptions {\n baseUrl?: string;\n /** Partner API key (X-API-Key). Without one, quotes carry a 0.2% platform fee. */\n apiKey?: string;\n /** Legacy JWT bearer token — same fee waiver as apiKey. */\n jwt?: string;\n fetch?: typeof globalThis.fetch;\n}\n\nexport interface OneClickClient {\n /** List supported assets; each entry's assetId is used in quotes. */\n tokens(): Promise<OneClickToken[]>;\n /** Request a quote. dry:true previews pricing; dry:false allocates the depositAddress. */\n quote(request: OneClickQuoteRequest): Promise<OneClickQuoteResponse>;\n /** Poll swap execution by deposit address. */\n status(params: {\n depositAddress: string;\n depositMemo?: string;\n }): Promise<OneClickStatusResponse>;\n /** Optional accelerator: report the deposit tx hash. */\n submitDeposit(\n request: OneClickSubmitDepositRequest,\n ): Promise<OneClickStatusResponse>;\n /** INTENTS deposit type: server builds the swap_transfer intent to sign. */\n generateIntent(\n request: OneClickGenerateIntentRequest,\n ): Promise<OneClickGenerateIntentResponse>;\n /** INTENTS deposit type: submit the signed intent. */\n submitIntent(params: {\n signedData: SignedIntent;\n }): Promise<OneClickSubmitIntentResponse>;\n}\n\nasync function parseBody(response: Response): Promise<unknown> {\n const text = await response.text();\n try {\n return text ? JSON.parse(text) : null;\n } catch {\n return text;\n }\n}\n\n/**\n * Zero-dependency typed client for the hosted 1Click swap API.\n * Works unauthenticated (0.2% platform fee baked into quotes); pass an\n * apiKey from https://partners.near-intents.org/ to waive it.\n */\nexport function createOneClickClient(\n options: OneClickClientOptions = {},\n): OneClickClient {\n const baseUrl = (options.baseUrl ?? ONE_CLICK_BASE_URL).replace(/\\/$/, \"\");\n const fetchImplementation = options.fetch ?? globalThis.fetch;\n if (typeof fetchImplementation !== \"function\") {\n throw new Error(\"A fetch implementation is required\");\n }\n\n const authHeaders: Record<string, string> = {};\n if (options.apiKey) authHeaders[\"X-API-Key\"] = options.apiKey;\n if (options.jwt) authHeaders.Authorization = `Bearer ${options.jwt}`;\n\n async function request<T>(\n method: \"GET\" | \"POST\",\n path: string,\n body?: unknown,\n ): Promise<T> {\n // Content-Type only when a body exists — a bodyless GET with\n // application/json forces an unnecessary CORS preflight in browsers.\n const headers =\n body === undefined\n ? authHeaders\n : { ...authHeaders, \"Content-Type\": \"application/json\" };\n const response = await fetchImplementation(`${baseUrl}${path}`, {\n method,\n headers,\n ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n });\n const parsed = await parseBody(response);\n if (!response.ok) {\n const detail =\n parsed && typeof parsed === \"object\" && \"message\" in parsed\n ? ` — ${JSON.stringify((parsed as { message: unknown }).message)}`\n : \"\";\n throw new IntentsHttpError(\n `1Click ${method} ${path} failed with ${response.status}${detail}`,\n response.status,\n parsed,\n );\n }\n return parsed as T;\n }\n\n return {\n tokens: () => request(\"GET\", \"/v0/tokens\"),\n quote: (quoteRequest) => request(\"POST\", \"/v0/quote\", quoteRequest),\n status: ({ depositAddress, depositMemo }) => {\n const query = new URLSearchParams({ depositAddress });\n if (depositMemo) query.set(\"depositMemo\", depositMemo);\n return request(\"GET\", `/v0/status?${query}`);\n },\n submitDeposit: (submitRequest) =>\n request(\"POST\", \"/v0/deposit/submit\", submitRequest),\n generateIntent: ({ standard = \"nep413\", signerId, depositAddress }) =>\n request(\"POST\", \"/v0/generate-intent\", {\n type: \"swap_transfer\",\n standard,\n signerId,\n depositAddress,\n }),\n submitIntent: ({ signedData }) =>\n request(\"POST\", \"/v0/submit-intent\", {\n type: \"swap_transfer\",\n signedData,\n }),\n };\n}\n","import { base64ToBytes, bytesToBase64, toBase58 } from \"@fastnear/utils\";\nimport {\n INTENTS_CONTRACT_ID,\n type Intent,\n type IntentMessage,\n type IntentSigner,\n type SignIntentsParams,\n type GeneratedUnsignedIntent,\n type SignPayloadOptions,\n type SignedIntentNep413,\n type UnsignedNep413Payload,\n} from \"./types.js\";\n\n/** Crypto-random 32-byte NEP-413 nonce (the verifier's replay nonce). */\nexport function randomNonce(): Uint8Array {\n return crypto.getRandomValues(new Uint8Array(32));\n}\n\nconst DEFAULT_DEADLINE_MS = 5 * 60 * 1000;\n\n/** ISO-8601 deadline `ms` milliseconds from now (default 5 minutes). */\nexport function defaultDeadline(ms: number = DEFAULT_DEADLINE_MS): string {\n return new Date(Date.now() + ms).toISOString();\n}\n\n/** Build the inner intent message that gets signed. */\nexport function buildIntentMessage({\n signerId,\n intents,\n deadline,\n}: {\n signerId: string;\n intents: Intent[];\n deadline?: string;\n}): IntentMessage {\n if (!signerId) throw new Error(\"signerId is required\");\n if (!Array.isArray(intents) || intents.length === 0) {\n throw new Error(\"At least one intent is required\");\n }\n return {\n signer_id: signerId,\n deadline: deadline ?? defaultDeadline(),\n intents,\n };\n}\n\n/**\n * Encode a NEP-413 signature the way intents.near expects it:\n * `ed25519:<base58>` (or `secp256k1:<base58>` for 65-byte signatures).\n *\n * NEAR wallets return the signature as plain base64 per NEP-413 — passing\n * that through unconverted is the most common integration bug.\n */\nexport function encodeIntentSignature(\n signature: string | Uint8Array,\n): string {\n if (typeof signature === \"string\") {\n if (\n signature.startsWith(\"ed25519:\") ||\n signature.startsWith(\"secp256k1:\")\n ) {\n return signature;\n }\n return encodeIntentSignature(base64ToBytes(signature));\n }\n if (signature.length === 64) return `ed25519:${toBase58(signature)}`;\n if (signature.length === 65) return `secp256k1:${toBase58(signature)}`;\n throw new Error(\n `Unsupported NEP-413 signature length: ${signature.length} (expected 64 or 65 bytes)`,\n );\n}\n\n/** Ensure a public key string carries its curve prefix. */\nexport function normalizeIntentPublicKey(publicKey: string): string {\n if (!publicKey) throw new Error(\"A public key is required\");\n return publicKey.includes(\":\") ? publicKey : `ed25519:${publicKey}`;\n}\n\n/**\n * Assemble the signed MultiPayload from NEP-413 parts. Accepts the\n * signature as wallet base64, raw bytes, or an already-prefixed string.\n */\nexport function toSignedIntent({\n message,\n nonce,\n recipient = INTENTS_CONTRACT_ID,\n publicKey,\n signature,\n callbackUrl,\n}: {\n message: IntentMessage | string;\n nonce: Uint8Array;\n recipient?: string;\n publicKey: string;\n signature: string | Uint8Array;\n callbackUrl?: string;\n}): SignedIntentNep413 {\n if (nonce.length !== 32) {\n throw new Error(`NEP-413 nonce must be exactly 32 bytes, got ${nonce.length}`);\n }\n return {\n standard: \"nep413\",\n payload: {\n message: typeof message === \"string\" ? message : JSON.stringify(message),\n nonce: bytesToBase64(nonce),\n recipient,\n ...(callbackUrl ? { callbackUrl } : {}),\n },\n public_key: normalizeIntentPublicKey(publicKey),\n signature: encodeIntentSignature(signature),\n };\n}\n\n/**\n * Normalize an unsigned payload as 1Click's generate-intent returns it.\n * Accepts either the bare payload or the `{ standard, payload }` wrapper,\n * and decodes a base64 nonce string to bytes.\n */\nexport function unsignedPayloadParts(\n input: GeneratedUnsignedIntent,\n): { message: string; nonce: Uint8Array; recipient: string; callbackUrl?: string } {\n const payload =\n \"payload\" in input && typeof input.payload === \"object\"\n ? input.payload\n : (input as UnsignedNep413Payload);\n if (\n \"standard\" in input &&\n typeof input.standard === \"string\" &&\n input.standard !== \"nep413\"\n ) {\n throw new Error(\n `This signer only signs nep413 payloads; got standard \"${input.standard}\"`,\n );\n }\n if (typeof payload?.message !== \"string\" || typeof payload?.recipient !== \"string\") {\n throw new Error(\"Unsigned payload must carry message and recipient strings\");\n }\n const nonce =\n typeof payload.nonce === \"string\"\n ? base64ToBytes(payload.nonce)\n : payload.nonce;\n if (!(nonce instanceof Uint8Array) || nonce.length !== 32) {\n throw new Error(\"Unsigned payload nonce must decode to exactly 32 bytes\");\n }\n return {\n message: payload.message,\n nonce,\n recipient: payload.recipient,\n ...(payload.callbackUrl ? { callbackUrl: payload.callbackUrl } : {}),\n };\n}\n\nfunction assertExpectedRecipient(\n recipient: string,\n options?: SignPayloadOptions,\n): void {\n const expected = options?.expectedRecipient ?? INTENTS_CONTRACT_ID;\n if (recipient !== expected) {\n throw new Error(\n `Refusing to sign a payload for recipient \"${recipient}\" — expected \"${expected}\". ` +\n \"Pass { expectedRecipient } only when intentionally targeting a different verifier.\",\n );\n }\n}\n\n/** Best-effort signer_id extraction from an intent-message JSON string. */\nfunction signerIdFromMessage(message: string): string | undefined {\n try {\n const parsed = JSON.parse(message);\n return typeof parsed?.signer_id === \"string\" ? parsed.signer_id : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The @fastnear/wallet surface this package needs — structural, so any\n * object with a NEP-413 `signMessage` (and optionally `accountId`) works.\n */\nexport interface FastNearWalletLike {\n accountId?(options?: { network?: \"mainnet\" | \"testnet\" }): string | null;\n signMessage(params: {\n message: string;\n recipient: string;\n nonce: Uint8Array;\n network?: \"mainnet\" | \"testnet\";\n }): Promise<{ accountId: string; publicKey: string; signature: string }>;\n}\n\nexport interface WalletIntentSignerOptions {\n wallet: FastNearWalletLike;\n /** NEAR Intents is mainnet-oriented; override only for test deployments. */\n network?: \"mainnet\" | \"testnet\";\n}\n\n/**\n * Sign intent messages with a connected FastNEAR wallet via NEP-413.\n *\n * NEP-413 requires a full-access key, so wallets sign with the account's\n * own key — FunctionCall-access session keys cannot authorize intents.\n * The wallet's base64 signature is re-encoded to `ed25519:<base58>`.\n */\nexport function createWalletIntentSigner({\n wallet,\n network = \"mainnet\",\n}: WalletIntentSignerOptions): IntentSigner {\n if (!wallet || typeof wallet.signMessage !== \"function\") {\n throw new Error(\n \"A FastNEAR wallet module with signMessage is required (connect @fastnear/wallet first)\",\n );\n }\n\n async function signParts({\n message,\n nonce,\n recipient,\n callbackUrl,\n expectedSigner,\n }: {\n message: string;\n nonce: Uint8Array;\n recipient: string;\n callbackUrl?: string;\n expectedSigner?: string;\n }): Promise<SignedIntentNep413> {\n if (callbackUrl) {\n // NEP-413 binds callbackUrl into the signed digest, but the wallet\n // signMessage transport has no callbackUrl parameter — signing would\n // produce a payload that advertises a callbackUrl the signature does\n // not cover, which the verifier rejects.\n throw new Error(\n \"Wallet intent signing cannot bind callbackUrl payloads; use the local signer or drop callbackUrl\",\n );\n }\n const signed = await wallet.signMessage({\n message,\n recipient,\n nonce,\n network,\n });\n\n if (expectedSigner && signed.accountId && signed.accountId !== expectedSigner) {\n throw new Error(\n `Wallet signed as ${signed.accountId} but the intent names ${expectedSigner}; reconnect the intended account`,\n );\n }\n\n return toSignedIntent({\n message,\n nonce,\n recipient,\n publicKey: signed.publicKey,\n signature: signed.signature,\n callbackUrl,\n });\n }\n\n return {\n async signIntents(params: SignIntentsParams): Promise<SignedIntentNep413> {\n const signerId =\n params.signerId ??\n (typeof wallet.accountId === \"function\"\n ? wallet.accountId({ network })\n : null);\n if (!signerId) {\n throw new Error(`No wallet account connected on ${network}`);\n }\n\n const message = buildIntentMessage({\n signerId,\n intents: params.intents,\n deadline: params.deadline,\n });\n return signParts({\n message: JSON.stringify(message),\n nonce: params.nonce ?? randomNonce(),\n recipient: params.verifyingContract ?? INTENTS_CONTRACT_ID,\n expectedSigner: signerId,\n });\n },\n\n async signPayload(\n payload: GeneratedUnsignedIntent,\n options?: SignPayloadOptions,\n ): Promise<SignedIntentNep413> {\n const parts = unsignedPayloadParts(payload);\n assertExpectedRecipient(parts.recipient, options);\n return signParts({\n ...parts,\n expectedSigner: signerIdFromMessage(parts.message),\n });\n },\n };\n}\n","import { INTENTS_CONTRACT_ID, type IntentsTokenId } from \"./types.js\";\n\n/** Gas / deposit defaults for verifier interactions. */\nexport const FT_TRANSFER_CALL_GAS = \"100000000000000\"; // 100 TGas\nexport const WITHDRAW_GAS = \"100000000000000\"; // 100 TGas\nexport const WRAP_NEAR_GAS = \"30000000000000\"; // 30 TGas\nexport const ONE_YOCTO = \"1\";\n\n/** wNEAR contract — native NEAR must be wrapped before depositing. */\nexport const WRAP_NEAR_CONTRACT_ID = \"wrap.near\";\n\n/**\n * The flat FastNEAR action shape. near.sendTx serializes these fields\n * directly, and @fastnear/wallet converts flat actions for near-connect\n * wallets — so one shape works on both signing paths.\n */\nexport interface FunctionCallActionShape {\n type: \"FunctionCall\";\n methodName: string;\n args: Record<string, unknown>;\n gas: string;\n deposit: string;\n}\n\n/**\n * Build the `ft_transfer_call` action that deposits a NEP-141 token into the\n * verifier. Apply it ON the token contract:\n *\n * near.sendTx({ receiverId: \"usdt.tether-token.near\",\n * actions: [ftDepositAction({ amount })] })\n *\n * `msg` semantics (per the verifier docs): \"\" credits the sender; an\n * account-id string credits that account (`creditTo`); a JSON string enables\n * execute_intents-on-deposit. Native NEAR is rejected by the verifier —\n * wrap it first (see wrapNearAction).\n */\nexport function ftDepositAction({\n amount,\n creditTo,\n msg,\n verifierId = INTENTS_CONTRACT_ID,\n gas = FT_TRANSFER_CALL_GAS,\n}: {\n amount: string;\n creditTo?: string;\n msg?: string;\n verifierId?: string;\n gas?: string;\n}): FunctionCallActionShape {\n if (creditTo !== undefined && msg !== undefined) {\n throw new Error(\"Pass either creditTo or msg, not both\");\n }\n return {\n type: \"FunctionCall\",\n methodName: \"ft_transfer_call\",\n args: {\n receiver_id: verifierId,\n amount,\n msg: msg ?? creditTo ?? \"\",\n },\n gas,\n deposit: ONE_YOCTO,\n };\n}\n\n/**\n * Build the `near_deposit` action that wraps native NEAR into wNEAR.\n * Apply it ON wrap.near:\n *\n * near.sendTx({ receiverId: \"wrap.near\",\n * actions: [wrapNearAction({ amountYocto })] })\n */\nexport function wrapNearAction({\n amountYocto,\n gas = WRAP_NEAR_GAS,\n}: {\n amountYocto: string;\n gas?: string;\n}): FunctionCallActionShape {\n return {\n type: \"FunctionCall\",\n methodName: \"near_deposit\",\n args: {},\n gas,\n deposit: amountYocto,\n };\n}\n\n/**\n * Build the direct-call `ft_withdraw` action that moves a NEP-141 token out\n * of the verifier back to a NEAR account. Apply it ON intents.near. `token`\n * is the plain contract id (no `nep141:` prefix). Omit `msg` so failed\n * withdrawals stay refundable.\n */\nexport function ftWithdrawAction({\n token,\n receiverId,\n amount,\n memo,\n msg,\n storageDeposit,\n gas = WITHDRAW_GAS,\n}: {\n token: string;\n receiverId: string;\n amount: string;\n memo?: string;\n msg?: string;\n storageDeposit?: string;\n gas?: string;\n}): FunctionCallActionShape {\n if (token.includes(\":\")) {\n throw new Error(\n `ft_withdraw takes the plain token contract id, not a prefixed multi-token id: ${token}`,\n );\n }\n return {\n type: \"FunctionCall\",\n methodName: \"ft_withdraw\",\n args: {\n token,\n receiver_id: receiverId,\n amount,\n ...(memo !== undefined ? { memo } : {}),\n ...(msg !== undefined ? { msg } : {}),\n ...(storageDeposit !== undefined\n ? { storage_deposit: storageDeposit }\n : {}),\n },\n gas,\n deposit: ONE_YOCTO,\n };\n}\n\n/** A near.view-compatible function, injected so this package stays api-free. */\nexport type ViewFunction = (params: {\n contractId: string;\n methodName: string;\n args: Record<string, unknown>;\n}) => Promise<unknown>;\n\n/** Read one internal balance from the verifier's NEP-245 ledger. */\nexport async function mtBalance({\n accountId,\n tokenId,\n view,\n verifierId = INTENTS_CONTRACT_ID,\n}: {\n accountId: string;\n tokenId: IntentsTokenId;\n view: ViewFunction;\n verifierId?: string;\n}): Promise<string> {\n const result = await view({\n contractId: verifierId,\n methodName: \"mt_balance_of\",\n args: { account_id: accountId, token_id: tokenId },\n });\n return String(result ?? \"0\");\n}\n\n/**\n * Read many internal balances in one view call. Returns a map keyed by\n * token id (the RPC returns base-unit strings in request order).\n */\nexport async function mtBatchBalances({\n accountId,\n tokenIds,\n view,\n verifierId = INTENTS_CONTRACT_ID,\n}: {\n accountId: string;\n tokenIds: IntentsTokenId[];\n view: ViewFunction;\n verifierId?: string;\n}): Promise<Record<IntentsTokenId, string>> {\n const result = (await view({\n contractId: verifierId,\n methodName: \"mt_batch_balance_of\",\n args: { account_id: accountId, token_ids: tokenIds },\n })) as unknown[];\n if (!Array.isArray(result) || result.length !== tokenIds.length) {\n throw new Error(\n `mt_batch_balance_of returned ${Array.isArray(result) ? result.length : typeof result} results for ${tokenIds.length} token ids`,\n );\n }\n return Object.fromEntries(\n tokenIds.map((tokenId, index) => [tokenId, String(result[index] ?? \"0\")]),\n );\n}\n","import { IntentsHttpError } from \"./one-click.js\";\nimport {\n SOLVER_RELAY_URL,\n type RelayPublishResult,\n type RelayQuote,\n type RelayQuoteParams,\n type RelayStatusResult,\n type SignedIntent,\n} from \"./types.js\";\n\nexport interface SolverRelayClientOptions {\n url?: string;\n /** Relay API key (X-API-Key header), issued via the partner dashboard. */\n apiKey?: string;\n fetch?: typeof globalThis.fetch;\n}\n\nexport interface SolverRelayClient {\n /** Ask connected solvers for quotes (relay-side timeout ~3s). null = no quotes. */\n quote(params: RelayQuoteParams): Promise<RelayQuote[] | null>;\n /** Publish one signed intent against the quote hashes it fills. */\n publishIntent(params: {\n signedData: SignedIntent;\n quoteHashes: string[];\n }): Promise<RelayPublishResult>;\n /** Publish a batch of signed intents. */\n publishIntents(params: {\n signedDatas: SignedIntent[];\n quoteHashes: string[];\n requote?: boolean;\n }): Promise<RelayPublishResult>;\n /** Poll a published intent: PENDING → TX_BROADCASTED → SETTLED. */\n getStatus(params: { intentHash: string }): Promise<RelayStatusResult>;\n}\n\n/** Error carrying the JSON-RPC error object from the solver relay. */\nexport class SolverRelayError extends Error {\n readonly rpcError: unknown;\n\n constructor(message: string, rpcError: unknown) {\n super(message);\n this.name = \"SolverRelayError\";\n this.rpcError = rpcError;\n }\n}\n\n/**\n * Zero-dependency JSON-RPC client for the NEAR Intents solver relay\n * (the message bus that brokers quotes between users and solvers and\n * submits matched intent bundles to intents.near).\n */\nexport function createSolverRelayClient(\n options: SolverRelayClientOptions = {},\n): SolverRelayClient {\n const url = options.url ?? SOLVER_RELAY_URL;\n const fetchImplementation = options.fetch ?? globalThis.fetch;\n if (typeof fetchImplementation !== \"function\") {\n throw new Error(\"A fetch implementation is required\");\n }\n\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (options.apiKey) headers[\"X-API-Key\"] = options.apiKey;\n\n let nextId = 0;\n\n async function call<T>(method: string, params: unknown): Promise<T> {\n const id = ++nextId;\n const response = await fetchImplementation(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ id, jsonrpc: \"2.0\", method, params: [params] }),\n });\n const text = await response.text();\n let parsed: unknown = null;\n try {\n parsed = text ? JSON.parse(text) : null;\n } catch {\n parsed = text;\n }\n if (!response.ok) {\n throw new IntentsHttpError(\n `Solver relay ${method} failed with ${response.status}`,\n response.status,\n parsed,\n );\n }\n const body = parsed as { result?: T; error?: unknown };\n if (body && typeof body === \"object\" && body.error != null) {\n throw new SolverRelayError(\n `Solver relay ${method} returned an error: ${JSON.stringify(body.error)}`,\n body.error,\n );\n }\n if (!body || typeof body !== \"object\" || !(\"result\" in body)) {\n throw new SolverRelayError(\n `Solver relay ${method} returned a malformed JSON-RPC envelope`,\n parsed,\n );\n }\n return body.result as T;\n }\n\n return {\n quote: (params) => call(\"quote\", params),\n publishIntent: ({ signedData, quoteHashes }) =>\n call(\"publish_intent\", {\n signed_data: signedData,\n quote_hashes: quoteHashes,\n }),\n publishIntents: ({ signedDatas, quoteHashes, requote }) =>\n call(\"publish_intents\", {\n signed_datas: signedDatas,\n quote_hashes: quoteHashes,\n ...(requote === undefined ? {} : { requote }),\n }),\n getStatus: ({ intentHash }) =>\n call(\"get_status\", { intent_hash: intentHash }),\n };\n}\n"],"mappings":"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","names":[]}
|