@t402/ton 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/exact/client/index.d.ts +61 -2
- package/dist/cjs/exact/client/index.js +26 -2
- package/dist/cjs/exact/client/index.js.map +1 -1
- package/dist/cjs/exact/facilitator/index.d.ts +62 -2
- package/dist/cjs/exact/facilitator/index.js +10 -2
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/server/index.d.ts +42 -1
- package/dist/cjs/exact/server/index.js +17 -2
- package/dist/cjs/exact/server/index.js.map +1 -1
- package/dist/cjs/index.d.ts +6 -1
- package/dist/cjs/index.js +503 -9
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/chunk-P6JLVB4E.mjs +300 -0
- package/dist/esm/chunk-P6JLVB4E.mjs.map +1 -0
- package/dist/esm/chunk-UB4QVIUC.mjs +266 -0
- package/dist/esm/chunk-UB4QVIUC.mjs.map +1 -0
- package/dist/esm/{chunk-ZCMWKFVA.mjs → chunk-XNO6XEWS.mjs} +25 -2
- package/dist/esm/chunk-XNO6XEWS.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +61 -2
- package/dist/esm/exact/client/index.mjs +5 -3
- package/dist/esm/exact/facilitator/index.d.mts +62 -2
- package/dist/esm/exact/facilitator/index.mjs +6 -254
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/server/index.d.mts +42 -1
- package/dist/esm/exact/server/index.mjs +6 -208
- package/dist/esm/exact/server/index.mjs.map +1 -1
- package/dist/esm/index.d.mts +6 -1
- package/dist/esm/index.mjs +12 -4
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/esm/chunk-RST5PY7E.mjs +0 -85
- package/dist/esm/chunk-RST5PY7E.mjs.map +0 -1
- package/dist/esm/chunk-ZCMWKFVA.mjs.map +0 -1
|
@@ -1,258 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// src/exact/facilitator/scheme.ts
|
|
8
|
-
import { Cell } from "@ton/core";
|
|
9
|
-
var ExactTonScheme = class {
|
|
10
|
-
/**
|
|
11
|
-
* Creates a new ExactTonScheme facilitator instance.
|
|
12
|
-
*
|
|
13
|
-
* @param signer - The TON signer for facilitator operations
|
|
14
|
-
* @param config - Optional configuration
|
|
15
|
-
*/
|
|
16
|
-
constructor(signer, config = {}) {
|
|
17
|
-
this.signer = signer;
|
|
18
|
-
this.scheme = SCHEME_EXACT;
|
|
19
|
-
this.caipFamily = "ton:*";
|
|
20
|
-
this.config = config;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Get mechanism-specific extra data for the supported kinds endpoint.
|
|
24
|
-
* For TON, optionally returns gas sponsor address if configured.
|
|
25
|
-
*
|
|
26
|
-
* @param network - The network identifier
|
|
27
|
-
* @returns Extra data object or undefined
|
|
28
|
-
*/
|
|
29
|
-
getExtra(network) {
|
|
30
|
-
void network;
|
|
31
|
-
if (this.config.canSponsorGas) {
|
|
32
|
-
const addresses = this.signer.getAddresses();
|
|
33
|
-
if (addresses.length > 0) {
|
|
34
|
-
return {
|
|
35
|
-
gasSponsor: addresses[0]
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return void 0;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Get signer addresses used by this facilitator.
|
|
43
|
-
* Returns all addresses this facilitator can use for operations.
|
|
44
|
-
*
|
|
45
|
-
* @param network - The network identifier
|
|
46
|
-
* @returns Array of facilitator addresses
|
|
47
|
-
*/
|
|
48
|
-
getSigners(network) {
|
|
49
|
-
void network;
|
|
50
|
-
return [...this.signer.getAddresses()];
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Verifies a payment payload.
|
|
54
|
-
*
|
|
55
|
-
* Performs comprehensive validation:
|
|
56
|
-
* 1. Scheme and network matching
|
|
57
|
-
* 2. BOC format validation
|
|
58
|
-
* 3. Message structure verification
|
|
59
|
-
* 4. Authorization expiry check
|
|
60
|
-
* 5. Balance verification
|
|
61
|
-
* 6. Amount and recipient validation
|
|
62
|
-
*
|
|
63
|
-
* @param payload - The payment payload to verify
|
|
64
|
-
* @param requirements - The payment requirements
|
|
65
|
-
* @returns Promise resolving to verification response
|
|
66
|
-
*/
|
|
67
|
-
async verify(payload, requirements) {
|
|
68
|
-
const tonPayload = payload.payload;
|
|
69
|
-
const authorization = tonPayload.authorization;
|
|
70
|
-
if (payload.accepted.scheme !== SCHEME_EXACT || requirements.scheme !== SCHEME_EXACT) {
|
|
71
|
-
return {
|
|
72
|
-
isValid: false,
|
|
73
|
-
invalidReason: "unsupported_scheme",
|
|
74
|
-
payer: authorization.from
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
try {
|
|
78
|
-
const payloadNetwork = normalizeNetwork(payload.accepted.network);
|
|
79
|
-
const requirementsNetwork = normalizeNetwork(requirements.network);
|
|
80
|
-
if (payloadNetwork !== requirementsNetwork) {
|
|
81
|
-
return {
|
|
82
|
-
isValid: false,
|
|
83
|
-
invalidReason: "network_mismatch",
|
|
84
|
-
payer: authorization.from
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
} catch {
|
|
88
|
-
return {
|
|
89
|
-
isValid: false,
|
|
90
|
-
invalidReason: "invalid_network",
|
|
91
|
-
payer: authorization.from
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
try {
|
|
95
|
-
Cell.fromBase64(tonPayload.signedBoc);
|
|
96
|
-
} catch {
|
|
97
|
-
return {
|
|
98
|
-
isValid: false,
|
|
99
|
-
invalidReason: "invalid_boc_format",
|
|
100
|
-
payer: authorization.from
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
const verifyResult = await this.signer.verifyMessage({
|
|
104
|
-
signedBoc: tonPayload.signedBoc,
|
|
105
|
-
expectedFrom: authorization.from,
|
|
106
|
-
expectedTransfer: {
|
|
107
|
-
jettonAmount: BigInt(authorization.jettonAmount),
|
|
108
|
-
destination: requirements.payTo,
|
|
109
|
-
jettonMaster: requirements.asset
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
if (!verifyResult.valid) {
|
|
113
|
-
return {
|
|
114
|
-
isValid: false,
|
|
115
|
-
invalidReason: verifyResult.reason || "message_verification_failed",
|
|
116
|
-
payer: authorization.from
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
120
|
-
if (authorization.validUntil < now + 30) {
|
|
121
|
-
return {
|
|
122
|
-
isValid: false,
|
|
123
|
-
invalidReason: "authorization_expired",
|
|
124
|
-
payer: authorization.from
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
try {
|
|
128
|
-
const balance = await this.signer.getJettonBalance({
|
|
129
|
-
ownerAddress: authorization.from,
|
|
130
|
-
jettonMasterAddress: requirements.asset
|
|
131
|
-
});
|
|
132
|
-
if (balance < BigInt(requirements.amount)) {
|
|
133
|
-
return {
|
|
134
|
-
isValid: false,
|
|
135
|
-
invalidReason: "insufficient_jetton_balance",
|
|
136
|
-
payer: authorization.from
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
} catch (error) {
|
|
140
|
-
console.warn("Could not verify Jetton balance:", error);
|
|
141
|
-
}
|
|
142
|
-
if (BigInt(authorization.jettonAmount) < BigInt(requirements.amount)) {
|
|
143
|
-
return {
|
|
144
|
-
isValid: false,
|
|
145
|
-
invalidReason: "insufficient_amount",
|
|
146
|
-
payer: authorization.from
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
if (!addressesEqual(authorization.to, requirements.payTo)) {
|
|
150
|
-
return {
|
|
151
|
-
isValid: false,
|
|
152
|
-
invalidReason: "recipient_mismatch",
|
|
153
|
-
payer: authorization.from
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
if (!addressesEqual(authorization.jettonMaster, requirements.asset)) {
|
|
157
|
-
return {
|
|
158
|
-
isValid: false,
|
|
159
|
-
invalidReason: "asset_mismatch",
|
|
160
|
-
payer: authorization.from
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
try {
|
|
164
|
-
const currentSeqno = await this.signer.getSeqno(authorization.from);
|
|
165
|
-
if (authorization.seqno < currentSeqno) {
|
|
166
|
-
return {
|
|
167
|
-
isValid: false,
|
|
168
|
-
invalidReason: "seqno_already_used",
|
|
169
|
-
payer: authorization.from
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
if (authorization.seqno > currentSeqno) {
|
|
173
|
-
return {
|
|
174
|
-
isValid: false,
|
|
175
|
-
invalidReason: "seqno_too_high",
|
|
176
|
-
payer: authorization.from
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
} catch (error) {
|
|
180
|
-
console.warn("Could not verify seqno:", error);
|
|
181
|
-
}
|
|
182
|
-
try {
|
|
183
|
-
const isDeployed = await this.signer.isDeployed(authorization.from);
|
|
184
|
-
if (!isDeployed) {
|
|
185
|
-
return {
|
|
186
|
-
isValid: false,
|
|
187
|
-
invalidReason: "wallet_not_deployed",
|
|
188
|
-
payer: authorization.from
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
} catch (error) {
|
|
192
|
-
console.warn("Could not verify wallet deployment:", error);
|
|
193
|
-
}
|
|
194
|
-
return {
|
|
195
|
-
isValid: true,
|
|
196
|
-
invalidReason: void 0,
|
|
197
|
-
payer: authorization.from
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Settles a payment by broadcasting the signed message.
|
|
202
|
-
*
|
|
203
|
-
* @param payload - The payment payload to settle
|
|
204
|
-
* @param requirements - The payment requirements
|
|
205
|
-
* @returns Promise resolving to settlement response
|
|
206
|
-
*/
|
|
207
|
-
async settle(payload, requirements) {
|
|
208
|
-
const tonPayload = payload.payload;
|
|
209
|
-
const verifyResult = await this.verify(payload, requirements);
|
|
210
|
-
if (!verifyResult.isValid) {
|
|
211
|
-
return {
|
|
212
|
-
success: false,
|
|
213
|
-
network: payload.accepted.network,
|
|
214
|
-
transaction: "",
|
|
215
|
-
errorReason: verifyResult.invalidReason ?? "verification_failed",
|
|
216
|
-
payer: tonPayload.authorization.from
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
try {
|
|
220
|
-
const txHash = await this.signer.sendExternalMessage(tonPayload.signedBoc);
|
|
221
|
-
const confirmation = await this.signer.waitForTransaction({
|
|
222
|
-
address: tonPayload.authorization.from,
|
|
223
|
-
seqno: tonPayload.authorization.seqno + 1,
|
|
224
|
-
// Wait for next seqno
|
|
225
|
-
timeout: 6e4
|
|
226
|
-
// 60 second timeout
|
|
227
|
-
});
|
|
228
|
-
if (!confirmation.success) {
|
|
229
|
-
return {
|
|
230
|
-
success: false,
|
|
231
|
-
errorReason: confirmation.error || "transaction_not_confirmed",
|
|
232
|
-
transaction: txHash,
|
|
233
|
-
network: payload.accepted.network,
|
|
234
|
-
payer: tonPayload.authorization.from
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
return {
|
|
238
|
-
success: true,
|
|
239
|
-
transaction: confirmation.hash || txHash,
|
|
240
|
-
network: payload.accepted.network,
|
|
241
|
-
payer: tonPayload.authorization.from
|
|
242
|
-
};
|
|
243
|
-
} catch (error) {
|
|
244
|
-
console.error("Failed to settle TON transaction:", error);
|
|
245
|
-
return {
|
|
246
|
-
success: false,
|
|
247
|
-
errorReason: "transaction_failed",
|
|
248
|
-
transaction: "",
|
|
249
|
-
network: payload.accepted.network,
|
|
250
|
-
payer: tonPayload.authorization.from
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
};
|
|
2
|
+
ExactTonScheme,
|
|
3
|
+
registerExactTonScheme
|
|
4
|
+
} from "../../chunk-UB4QVIUC.mjs";
|
|
5
|
+
import "../../chunk-6LOUEHJT.mjs";
|
|
255
6
|
export {
|
|
256
|
-
ExactTonScheme
|
|
7
|
+
ExactTonScheme,
|
|
8
|
+
registerExactTonScheme
|
|
257
9
|
};
|
|
258
10
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/exact/facilitator/scheme.ts"],"sourcesContent":["/**\n * TON Facilitator Scheme Implementation\n *\n * Verifies and settles TON Jetton payments using the exact scheme.\n * Validates signed messages and broadcasts transactions to the network.\n */\n\nimport { Cell } from \"@ton/core\";\nimport type {\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@t402/core/types\";\nimport type { FacilitatorTonSigner } from \"../../signer.js\";\nimport type { ExactTonPayloadV2 } from \"../../types.js\";\nimport { SCHEME_EXACT } from \"../../constants.js\";\nimport { addressesEqual, normalizeNetwork } from \"../../utils.js\";\n\n/**\n * Configuration options for ExactTonScheme facilitator\n */\nexport interface ExactTonSchemeConfig {\n /** Whether this facilitator can sponsor gas for transactions */\n canSponsorGas?: boolean;\n}\n\n/**\n * TON facilitator implementation for the Exact payment scheme.\n *\n * Verifies signed Jetton transfer messages and broadcasts them\n * to the TON network to complete payments.\n */\nexport class ExactTonScheme implements SchemeNetworkFacilitator {\n readonly scheme = SCHEME_EXACT;\n readonly caipFamily = \"ton:*\";\n private config: ExactTonSchemeConfig;\n\n /**\n * Creates a new ExactTonScheme facilitator instance.\n *\n * @param signer - The TON signer for facilitator operations\n * @param config - Optional configuration\n */\n constructor(\n private readonly signer: FacilitatorTonSigner,\n config: ExactTonSchemeConfig = {},\n ) {\n this.config = config;\n }\n\n /**\n * Get mechanism-specific extra data for the supported kinds endpoint.\n * For TON, optionally returns gas sponsor address if configured.\n *\n * @param network - The network identifier\n * @returns Extra data object or undefined\n */\n getExtra(network: string): Record<string, unknown> | undefined {\n void network;\n\n if (this.config.canSponsorGas) {\n const addresses = this.signer.getAddresses();\n if (addresses.length > 0) {\n return {\n gasSponsor: addresses[0],\n };\n }\n }\n\n return undefined;\n }\n\n /**\n * Get signer addresses used by this facilitator.\n * Returns all addresses this facilitator can use for operations.\n *\n * @param network - The network identifier\n * @returns Array of facilitator addresses\n */\n getSigners(network: string): string[] {\n void network;\n return [...this.signer.getAddresses()];\n }\n\n /**\n * Verifies a payment payload.\n *\n * Performs comprehensive validation:\n * 1. Scheme and network matching\n * 2. BOC format validation\n * 3. Message structure verification\n * 4. Authorization expiry check\n * 5. Balance verification\n * 6. Amount and recipient validation\n *\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @returns Promise resolving to verification response\n */\n async verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<VerifyResponse> {\n const tonPayload = payload.payload as ExactTonPayloadV2;\n const authorization = tonPayload.authorization;\n\n // Step 1: Verify scheme matches\n if (payload.accepted.scheme !== SCHEME_EXACT || requirements.scheme !== SCHEME_EXACT) {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer: authorization.from,\n };\n }\n\n // Step 2: Verify network matches\n try {\n const payloadNetwork = normalizeNetwork(payload.accepted.network);\n const requirementsNetwork = normalizeNetwork(requirements.network);\n\n if (payloadNetwork !== requirementsNetwork) {\n return {\n isValid: false,\n invalidReason: \"network_mismatch\",\n payer: authorization.from,\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: \"invalid_network\",\n payer: authorization.from,\n };\n }\n\n // Step 3: Parse and validate the signed BOC\n try {\n Cell.fromBase64(tonPayload.signedBoc);\n } catch {\n return {\n isValid: false,\n invalidReason: \"invalid_boc_format\",\n payer: authorization.from,\n };\n }\n\n // Step 4: Verify the message structure and parameters\n const verifyResult = await this.signer.verifyMessage({\n signedBoc: tonPayload.signedBoc,\n expectedFrom: authorization.from,\n expectedTransfer: {\n jettonAmount: BigInt(authorization.jettonAmount),\n destination: requirements.payTo,\n jettonMaster: requirements.asset,\n },\n });\n\n if (!verifyResult.valid) {\n return {\n isValid: false,\n invalidReason: verifyResult.reason || \"message_verification_failed\",\n payer: authorization.from,\n };\n }\n\n // Step 5: Check validUntil is in the future (with 30 second buffer)\n const now = Math.floor(Date.now() / 1000);\n if (authorization.validUntil < now + 30) {\n return {\n isValid: false,\n invalidReason: \"authorization_expired\",\n payer: authorization.from,\n };\n }\n\n // Step 6: Verify Jetton balance\n try {\n const balance = await this.signer.getJettonBalance({\n ownerAddress: authorization.from,\n jettonMasterAddress: requirements.asset,\n });\n\n if (balance < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_jetton_balance\",\n payer: authorization.from,\n };\n }\n } catch (error) {\n // If we can't check balance, log warning but continue\n console.warn(\"Could not verify Jetton balance:\", error);\n }\n\n // Step 7: Verify amount is sufficient\n if (BigInt(authorization.jettonAmount) < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_amount\",\n payer: authorization.from,\n };\n }\n\n // Step 8: Verify recipient matches\n if (!addressesEqual(authorization.to, requirements.payTo)) {\n return {\n isValid: false,\n invalidReason: \"recipient_mismatch\",\n payer: authorization.from,\n };\n }\n\n // Step 9: Verify Jetton master matches\n if (!addressesEqual(authorization.jettonMaster, requirements.asset)) {\n return {\n isValid: false,\n invalidReason: \"asset_mismatch\",\n payer: authorization.from,\n };\n }\n\n // Step 10: Check seqno hasn't been used (replay protection)\n try {\n const currentSeqno = await this.signer.getSeqno(authorization.from);\n if (authorization.seqno < currentSeqno) {\n return {\n isValid: false,\n invalidReason: \"seqno_already_used\",\n payer: authorization.from,\n };\n }\n if (authorization.seqno > currentSeqno) {\n return {\n isValid: false,\n invalidReason: \"seqno_too_high\",\n payer: authorization.from,\n };\n }\n } catch (error) {\n console.warn(\"Could not verify seqno:\", error);\n }\n\n // Step 11: Verify wallet is deployed\n try {\n const isDeployed = await this.signer.isDeployed(authorization.from);\n if (!isDeployed) {\n return {\n isValid: false,\n invalidReason: \"wallet_not_deployed\",\n payer: authorization.from,\n };\n }\n } catch (error) {\n console.warn(\"Could not verify wallet deployment:\", error);\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer: authorization.from,\n };\n }\n\n /**\n * Settles a payment by broadcasting the signed message.\n *\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<SettleResponse> {\n const tonPayload = payload.payload as ExactTonPayloadV2;\n\n // Re-verify before settling\n const verifyResult = await this.verify(payload, requirements);\n if (!verifyResult.isValid) {\n return {\n success: false,\n network: payload.accepted.network,\n transaction: \"\",\n errorReason: verifyResult.invalidReason ?? \"verification_failed\",\n payer: tonPayload.authorization.from,\n };\n }\n\n try {\n // Send the pre-signed external message\n const txHash = await this.signer.sendExternalMessage(tonPayload.signedBoc);\n\n // Wait for confirmation\n const confirmation = await this.signer.waitForTransaction({\n address: tonPayload.authorization.from,\n seqno: tonPayload.authorization.seqno + 1, // Wait for next seqno\n timeout: 60000, // 60 second timeout\n });\n\n if (!confirmation.success) {\n return {\n success: false,\n errorReason: confirmation.error || \"transaction_not_confirmed\",\n transaction: txHash,\n network: payload.accepted.network,\n payer: tonPayload.authorization.from,\n };\n }\n\n return {\n success: true,\n transaction: confirmation.hash || txHash,\n network: payload.accepted.network,\n payer: tonPayload.authorization.from,\n };\n } catch (error) {\n console.error(\"Failed to settle TON transaction:\", error);\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payload.accepted.network,\n payer: tonPayload.authorization.from,\n };\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SchemeNetworkServer, MoneyParser, Price, Network, AssetAmount, PaymentRequirements } from '@t402/core/types';
|
|
2
|
+
import { t402ResourceServer } from '@t402/core/server';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* TON Server Scheme Implementation
|
|
@@ -132,4 +133,44 @@ declare class ExactTonScheme implements SchemeNetworkServer {
|
|
|
132
133
|
static isNetworkSupported(network: string): boolean;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Configuration options for registering TON schemes to an t402ResourceServer
|
|
138
|
+
*/
|
|
139
|
+
interface TonResourceServerConfig {
|
|
140
|
+
/**
|
|
141
|
+
* Optional specific networks to register
|
|
142
|
+
* If not provided, registers wildcard support (ton:*)
|
|
143
|
+
*/
|
|
144
|
+
networks?: Network[];
|
|
145
|
+
/**
|
|
146
|
+
* Optional scheme configuration (preferred Jetton, etc.)
|
|
147
|
+
*/
|
|
148
|
+
schemeConfig?: ExactTonSchemeConfig;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Registers TON exact payment schemes to an t402ResourceServer instance.
|
|
152
|
+
*
|
|
153
|
+
* This function registers:
|
|
154
|
+
* - V2: ton:* wildcard scheme with ExactTonScheme (or specific networks if provided)
|
|
155
|
+
*
|
|
156
|
+
* @param server - The t402ResourceServer instance to register schemes to
|
|
157
|
+
* @param config - Configuration for TON resource server registration
|
|
158
|
+
* @returns The server instance for chaining
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```typescript
|
|
162
|
+
* import { registerExactTonScheme } from "@t402/ton/exact/server/register";
|
|
163
|
+
* import { t402ResourceServer } from "@t402/core/server";
|
|
164
|
+
*
|
|
165
|
+
* const server = new t402ResourceServer(facilitatorClient);
|
|
166
|
+
* registerExactTonScheme(server, {});
|
|
167
|
+
*
|
|
168
|
+
* // Or with specific Jetton preference
|
|
169
|
+
* registerExactTonScheme(server, {
|
|
170
|
+
* schemeConfig: { preferredJetton: "USDT" }
|
|
171
|
+
* });
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
declare function registerExactTonScheme(server: t402ResourceServer, config?: TonResourceServerConfig): t402ResourceServer;
|
|
175
|
+
|
|
176
|
+
export { ExactTonScheme, type ExactTonSchemeConfig, type TonResourceServerConfig, registerExactTonScheme };
|
|
@@ -1,212 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "../../chunk-RST5PY7E.mjs";
|
|
7
|
-
import {
|
|
8
|
-
SCHEME_EXACT,
|
|
9
|
-
normalizeNetwork
|
|
10
|
-
} from "../../chunk-6LOUEHJT.mjs";
|
|
11
|
-
|
|
12
|
-
// src/exact/server/scheme.ts
|
|
13
|
-
var ExactTonScheme = class {
|
|
14
|
-
constructor(config = {}) {
|
|
15
|
-
this.scheme = SCHEME_EXACT;
|
|
16
|
-
this.moneyParsers = [];
|
|
17
|
-
this.config = config;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Register a custom money parser in the parser chain.
|
|
21
|
-
* Multiple parsers can be registered - they will be tried in registration order.
|
|
22
|
-
* Each parser receives a decimal amount (e.g., 1.50 for $1.50).
|
|
23
|
-
* If a parser returns null, the next parser in the chain will be tried.
|
|
24
|
-
* The default parser is always the final fallback.
|
|
25
|
-
*
|
|
26
|
-
* @param parser - Custom function to convert amount to AssetAmount (or null to skip)
|
|
27
|
-
* @returns The server instance for chaining
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* tonServer.registerMoneyParser(async (amount, network) => {
|
|
31
|
-
* // Use custom Jetton for large amounts
|
|
32
|
-
* if (amount > 1000) {
|
|
33
|
-
* return {
|
|
34
|
-
* amount: (amount * 1e9).toString(),
|
|
35
|
-
* asset: "EQCustomJettonAddress...",
|
|
36
|
-
* extra: { tier: "premium" }
|
|
37
|
-
* };
|
|
38
|
-
* }
|
|
39
|
-
* return null; // Use next parser
|
|
40
|
-
* });
|
|
41
|
-
*/
|
|
42
|
-
registerMoneyParser(parser) {
|
|
43
|
-
this.moneyParsers.push(parser);
|
|
44
|
-
return this;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Parses a price into an asset amount.
|
|
48
|
-
* If price is already an AssetAmount, returns it directly.
|
|
49
|
-
* If price is Money (string | number), parses to decimal and tries custom parsers.
|
|
50
|
-
* Falls back to default conversion if all custom parsers return null.
|
|
51
|
-
*
|
|
52
|
-
* @param price - The price to parse
|
|
53
|
-
* @param network - The network to use
|
|
54
|
-
* @returns Promise that resolves to the parsed asset amount
|
|
55
|
-
*/
|
|
56
|
-
async parsePrice(price, network) {
|
|
57
|
-
const normalizedNetwork = normalizeNetwork(network);
|
|
58
|
-
if (typeof price === "object" && price !== null && "amount" in price) {
|
|
59
|
-
if (!price.asset) {
|
|
60
|
-
throw new Error(`Asset address must be specified for AssetAmount on network ${network}`);
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
amount: price.amount,
|
|
64
|
-
asset: price.asset,
|
|
65
|
-
extra: price.extra || {}
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
const amount = this.parseMoneyToDecimal(price);
|
|
69
|
-
for (const parser of this.moneyParsers) {
|
|
70
|
-
const result = await parser(amount, normalizedNetwork);
|
|
71
|
-
if (result !== null) {
|
|
72
|
-
return result;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return this.defaultMoneyConversion(amount, normalizedNetwork);
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Build payment requirements for this scheme/network combination.
|
|
79
|
-
* Adds TON-specific fields like gas sponsor if provided by facilitator.
|
|
80
|
-
*
|
|
81
|
-
* @param paymentRequirements - Base payment requirements with amount/asset already set
|
|
82
|
-
* @param supportedKind - The supported kind from facilitator's /supported endpoint
|
|
83
|
-
* @param extensionKeys - Extensions supported by the facilitator (unused)
|
|
84
|
-
* @returns Enhanced payment requirements ready to be sent to clients
|
|
85
|
-
*/
|
|
86
|
-
async enhancePaymentRequirements(paymentRequirements, supportedKind, extensionKeys) {
|
|
87
|
-
void extensionKeys;
|
|
88
|
-
const extra = { ...paymentRequirements.extra };
|
|
89
|
-
if (supportedKind.extra?.gasSponsor) {
|
|
90
|
-
extra.gasSponsor = supportedKind.extra.gasSponsor;
|
|
91
|
-
}
|
|
92
|
-
return {
|
|
93
|
-
...paymentRequirements,
|
|
94
|
-
extra
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Parse Money (string | number) to a decimal number.
|
|
99
|
-
* Handles formats like "$1.50", "1.50", 1.50, etc.
|
|
100
|
-
*
|
|
101
|
-
* @param money - The money value to parse
|
|
102
|
-
* @returns Decimal number
|
|
103
|
-
*/
|
|
104
|
-
parseMoneyToDecimal(money) {
|
|
105
|
-
if (typeof money === "number") {
|
|
106
|
-
return money;
|
|
107
|
-
}
|
|
108
|
-
const cleanMoney = money.replace(/^\$/, "").trim();
|
|
109
|
-
const amount = parseFloat(cleanMoney);
|
|
110
|
-
if (isNaN(amount)) {
|
|
111
|
-
throw new Error(`Invalid money format: ${money}`);
|
|
112
|
-
}
|
|
113
|
-
return amount;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Default money conversion implementation.
|
|
117
|
-
* Converts decimal amount to the preferred Jetton on the specified network.
|
|
118
|
-
*
|
|
119
|
-
* @param amount - The decimal amount (e.g., 1.50)
|
|
120
|
-
* @param network - The network to use
|
|
121
|
-
* @returns The parsed asset amount
|
|
122
|
-
*/
|
|
123
|
-
defaultMoneyConversion(amount, network) {
|
|
124
|
-
const jetton = this.getDefaultAsset(network);
|
|
125
|
-
const tokenAmount = this.convertToTokenAmount(amount.toString(), jetton.decimals);
|
|
126
|
-
return {
|
|
127
|
-
amount: tokenAmount,
|
|
128
|
-
asset: jetton.masterAddress,
|
|
129
|
-
extra: {
|
|
130
|
-
symbol: jetton.symbol,
|
|
131
|
-
name: jetton.name,
|
|
132
|
-
decimals: jetton.decimals
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Convert decimal amount to token units (e.g., 0.10 -> 100000 for 6-decimal tokens)
|
|
138
|
-
*
|
|
139
|
-
* @param decimalAmount - The decimal amount to convert
|
|
140
|
-
* @param decimals - Number of decimals for the token
|
|
141
|
-
* @returns The token amount as a string
|
|
142
|
-
*/
|
|
143
|
-
convertToTokenAmount(decimalAmount, decimals) {
|
|
144
|
-
const amount = parseFloat(decimalAmount);
|
|
145
|
-
if (isNaN(amount)) {
|
|
146
|
-
throw new Error(`Invalid amount: ${decimalAmount}`);
|
|
147
|
-
}
|
|
148
|
-
const tokenAmount = Math.floor(amount * Math.pow(10, decimals));
|
|
149
|
-
return tokenAmount.toString();
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Get the default asset info for a network.
|
|
153
|
-
* Priority: configured preferredJetton > USDT > first available
|
|
154
|
-
*
|
|
155
|
-
* @param network - The network to get asset info for
|
|
156
|
-
* @returns The Jetton configuration
|
|
157
|
-
*/
|
|
158
|
-
getDefaultAsset(network) {
|
|
159
|
-
if (this.config.preferredJetton) {
|
|
160
|
-
const preferred = getJettonConfig(network, this.config.preferredJetton);
|
|
161
|
-
if (preferred) return preferred;
|
|
162
|
-
}
|
|
163
|
-
const defaultJetton = getDefaultJetton(network);
|
|
164
|
-
if (defaultJetton) return defaultJetton;
|
|
165
|
-
throw new Error(`No Jettons configured for network ${network}`);
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Get Jetton info for a given symbol on a network
|
|
169
|
-
*
|
|
170
|
-
* @param symbol - The Jetton symbol (e.g., "USDT")
|
|
171
|
-
* @param network - The network to use
|
|
172
|
-
* @returns The Jetton configuration
|
|
173
|
-
*/
|
|
174
|
-
getAssetInfo(symbol, network) {
|
|
175
|
-
const jetton = getJettonConfig(network, symbol);
|
|
176
|
-
if (jetton) return jetton;
|
|
177
|
-
if (symbol.toUpperCase() === "USD") {
|
|
178
|
-
return this.getDefaultAsset(network);
|
|
179
|
-
}
|
|
180
|
-
throw new Error(`Unsupported Jetton: ${symbol} on network ${network}`);
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Get the number of decimals for a Jetton on a network
|
|
184
|
-
*
|
|
185
|
-
* @param network - The network to use
|
|
186
|
-
* @param jettonAddress - Optional Jetton address to look up
|
|
187
|
-
* @returns The number of decimals for the Jetton
|
|
188
|
-
*/
|
|
189
|
-
getAssetDecimals(network, jettonAddress) {
|
|
190
|
-
if (jettonAddress) {
|
|
191
|
-
const jetton = getJettonByAddress(network, jettonAddress);
|
|
192
|
-
if (jetton) return jetton.decimals;
|
|
193
|
-
}
|
|
194
|
-
return 6;
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Get all supported networks
|
|
198
|
-
*/
|
|
199
|
-
static getSupportedNetworks() {
|
|
200
|
-
return Object.keys(JETTON_REGISTRY);
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Check if a network is supported
|
|
204
|
-
*/
|
|
205
|
-
static isNetworkSupported(network) {
|
|
206
|
-
return network in JETTON_REGISTRY;
|
|
207
|
-
}
|
|
208
|
-
};
|
|
2
|
+
ExactTonScheme,
|
|
3
|
+
registerExactTonScheme
|
|
4
|
+
} from "../../chunk-P6JLVB4E.mjs";
|
|
5
|
+
import "../../chunk-6LOUEHJT.mjs";
|
|
209
6
|
export {
|
|
210
|
-
ExactTonScheme
|
|
7
|
+
ExactTonScheme,
|
|
8
|
+
registerExactTonScheme
|
|
211
9
|
};
|
|
212
10
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/exact/server/scheme.ts"],"sourcesContent":["/**\n * TON Server Scheme Implementation\n *\n * Handles price parsing and payment requirement enhancement for\n * TON Jetton payments using the exact scheme.\n */\n\nimport type {\n AssetAmount,\n Network,\n PaymentRequirements,\n Price,\n SchemeNetworkServer,\n MoneyParser,\n} from \"@t402/core/types\";\nimport { SCHEME_EXACT } from \"../../constants.js\";\nimport {\n getDefaultJetton,\n getJettonConfig,\n getJettonByAddress,\n JETTON_REGISTRY,\n} from \"../../tokens.js\";\nimport { normalizeNetwork } from \"../../utils.js\";\n\n/**\n * Configuration options for ExactTonScheme server\n */\nexport interface ExactTonSchemeConfig {\n /** Preferred Jetton symbol (e.g., \"USDT\"). Defaults to network's highest priority token. */\n preferredJetton?: string;\n}\n\n/**\n * TON server implementation for the Exact payment scheme.\n * Handles price parsing and converts user-friendly amounts to Jetton amounts.\n */\nexport class ExactTonScheme implements SchemeNetworkServer {\n readonly scheme = SCHEME_EXACT;\n private moneyParsers: MoneyParser[] = [];\n private config: ExactTonSchemeConfig;\n\n constructor(config: ExactTonSchemeConfig = {}) {\n this.config = config;\n }\n\n /**\n * Register a custom money parser in the parser chain.\n * Multiple parsers can be registered - they will be tried in registration order.\n * Each parser receives a decimal amount (e.g., 1.50 for $1.50).\n * If a parser returns null, the next parser in the chain will be tried.\n * The default parser is always the final fallback.\n *\n * @param parser - Custom function to convert amount to AssetAmount (or null to skip)\n * @returns The server instance for chaining\n *\n * @example\n * tonServer.registerMoneyParser(async (amount, network) => {\n * // Use custom Jetton for large amounts\n * if (amount > 1000) {\n * return {\n * amount: (amount * 1e9).toString(),\n * asset: \"EQCustomJettonAddress...\",\n * extra: { tier: \"premium\" }\n * };\n * }\n * return null; // Use next parser\n * });\n */\n registerMoneyParser(parser: MoneyParser): ExactTonScheme {\n this.moneyParsers.push(parser);\n return this;\n }\n\n /**\n * Parses a price into an asset amount.\n * If price is already an AssetAmount, returns it directly.\n * If price is Money (string | number), parses to decimal and tries custom parsers.\n * Falls back to default conversion if all custom parsers return null.\n *\n * @param price - The price to parse\n * @param network - The network to use\n * @returns Promise that resolves to the parsed asset amount\n */\n async parsePrice(price: Price, network: Network): Promise<AssetAmount> {\n // Normalize network to CAIP-2 format\n const normalizedNetwork = normalizeNetwork(network);\n\n // If already an AssetAmount, return it directly\n if (typeof price === \"object\" && price !== null && \"amount\" in price) {\n if (!price.asset) {\n throw new Error(`Asset address must be specified for AssetAmount on network ${network}`);\n }\n return {\n amount: price.amount,\n asset: price.asset,\n extra: price.extra || {},\n };\n }\n\n // Parse Money to decimal number\n const amount = this.parseMoneyToDecimal(price);\n\n // Try each custom money parser in order\n for (const parser of this.moneyParsers) {\n const result = await parser(amount, normalizedNetwork);\n if (result !== null) {\n return result;\n }\n }\n\n // All custom parsers returned null, use default conversion\n return this.defaultMoneyConversion(amount, normalizedNetwork);\n }\n\n /**\n * Build payment requirements for this scheme/network combination.\n * Adds TON-specific fields like gas sponsor if provided by facilitator.\n *\n * @param paymentRequirements - Base payment requirements with amount/asset already set\n * @param supportedKind - The supported kind from facilitator's /supported endpoint\n * @param extensionKeys - Extensions supported by the facilitator (unused)\n * @returns Enhanced payment requirements ready to be sent to clients\n */\n async enhancePaymentRequirements(\n paymentRequirements: PaymentRequirements,\n supportedKind: {\n t402Version: number;\n scheme: string;\n network: Network;\n extra?: Record<string, unknown>;\n },\n extensionKeys: string[],\n ): Promise<PaymentRequirements> {\n // Mark unused parameters to satisfy linter\n void extensionKeys;\n\n // Start with existing extra fields\n const extra = { ...paymentRequirements.extra };\n\n // Add gas sponsor from facilitator if provided\n if (supportedKind.extra?.gasSponsor) {\n extra.gasSponsor = supportedKind.extra.gasSponsor;\n }\n\n return {\n ...paymentRequirements,\n extra,\n };\n }\n\n /**\n * Parse Money (string | number) to a decimal number.\n * Handles formats like \"$1.50\", \"1.50\", 1.50, etc.\n *\n * @param money - The money value to parse\n * @returns Decimal number\n */\n private parseMoneyToDecimal(money: string | number): number {\n if (typeof money === \"number\") {\n return money;\n }\n\n // Remove $ sign and whitespace, then parse\n const cleanMoney = money.replace(/^\\$/, \"\").trim();\n const amount = parseFloat(cleanMoney);\n\n if (isNaN(amount)) {\n throw new Error(`Invalid money format: ${money}`);\n }\n\n return amount;\n }\n\n /**\n * Default money conversion implementation.\n * Converts decimal amount to the preferred Jetton on the specified network.\n *\n * @param amount - The decimal amount (e.g., 1.50)\n * @param network - The network to use\n * @returns The parsed asset amount\n */\n private defaultMoneyConversion(amount: number, network: Network): AssetAmount {\n const jetton = this.getDefaultAsset(network);\n\n // Convert decimal amount to token amount\n const tokenAmount = this.convertToTokenAmount(amount.toString(), jetton.decimals);\n\n return {\n amount: tokenAmount,\n asset: jetton.masterAddress,\n extra: {\n symbol: jetton.symbol,\n name: jetton.name,\n decimals: jetton.decimals,\n },\n };\n }\n\n /**\n * Convert decimal amount to token units (e.g., 0.10 -> 100000 for 6-decimal tokens)\n *\n * @param decimalAmount - The decimal amount to convert\n * @param decimals - Number of decimals for the token\n * @returns The token amount as a string\n */\n private convertToTokenAmount(decimalAmount: string, decimals: number): string {\n const amount = parseFloat(decimalAmount);\n if (isNaN(amount)) {\n throw new Error(`Invalid amount: ${decimalAmount}`);\n }\n // Convert to smallest unit (e.g., for USDT with 6 decimals: 0.10 * 10^6 = 100000)\n const tokenAmount = Math.floor(amount * Math.pow(10, decimals));\n return tokenAmount.toString();\n }\n\n /**\n * Get the default asset info for a network.\n * Priority: configured preferredJetton > USDT > first available\n *\n * @param network - The network to get asset info for\n * @returns The Jetton configuration\n */\n private getDefaultAsset(\n network: Network,\n ): { masterAddress: string; symbol: string; name: string; decimals: number } {\n // If a preferred Jetton is configured, try to use it\n if (this.config.preferredJetton) {\n const preferred = getJettonConfig(network, this.config.preferredJetton);\n if (preferred) return preferred;\n }\n\n // Use the network's default token (sorted by priority)\n const defaultJetton = getDefaultJetton(network);\n if (defaultJetton) return defaultJetton;\n\n throw new Error(`No Jettons configured for network ${network}`);\n }\n\n /**\n * Get Jetton info for a given symbol on a network\n *\n * @param symbol - The Jetton symbol (e.g., \"USDT\")\n * @param network - The network to use\n * @returns The Jetton configuration\n */\n private getAssetInfo(\n symbol: string,\n network: Network,\n ): { masterAddress: string; symbol: string; name: string; decimals: number } {\n const jetton = getJettonConfig(network, symbol);\n if (jetton) return jetton;\n\n // Fallback: treat \"USD\" as request for default stablecoin\n if (symbol.toUpperCase() === \"USD\") {\n return this.getDefaultAsset(network);\n }\n\n throw new Error(`Unsupported Jetton: ${symbol} on network ${network}`);\n }\n\n /**\n * Get the number of decimals for a Jetton on a network\n *\n * @param network - The network to use\n * @param jettonAddress - Optional Jetton address to look up\n * @returns The number of decimals for the Jetton\n */\n private getAssetDecimals(network: Network, jettonAddress?: string): number {\n if (jettonAddress) {\n const jetton = getJettonByAddress(network, jettonAddress);\n if (jetton) return jetton.decimals;\n }\n // Default to 6 decimals (USDT standard)\n return 6;\n }\n\n /**\n * Get all supported networks\n */\n static getSupportedNetworks(): string[] {\n return Object.keys(JETTON_REGISTRY);\n }\n\n /**\n * Check if a network is supported\n */\n static isNetworkSupported(network: string): boolean {\n return network in JETTON_REGISTRY;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
export { ExactTonScheme } from './exact/client/index.mjs';
|
|
1
|
+
export { ExactTonScheme, TonClientConfig, registerExactTonScheme as registerExactTonClientScheme } from './exact/client/index.mjs';
|
|
2
|
+
export { TonResourceServerConfig, registerExactTonScheme as registerExactTonServerScheme } from './exact/server/index.mjs';
|
|
2
3
|
export { C as ClientTonSigner, b as ExactTonPayload, E as ExactTonPayloadV2, F as FacilitatorTonSigner, S as SignMessageParams, T as TransactionConfirmation, V as VerifyMessageParams, c as VerifyMessageResult, W as WaitForTransactionParams, t as toClientTonSigner, a as toFacilitatorTonSigner } from './signer-CFiw2DST.mjs';
|
|
4
|
+
export { TonFacilitatorConfig, registerExactTonScheme as registerExactTonFacilitatorScheme } from './exact/facilitator/index.mjs';
|
|
3
5
|
import { Address, Cell } from '@ton/core';
|
|
4
6
|
import { Network } from '@t402/core/types';
|
|
7
|
+
import '@t402/core/client';
|
|
8
|
+
import '@t402/core/server';
|
|
9
|
+
import '@t402/core/facilitator';
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
12
|
* TON Jetton Token Configuration
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ExactTonScheme
|
|
3
|
-
|
|
2
|
+
ExactTonScheme,
|
|
3
|
+
registerExactTonScheme
|
|
4
|
+
} from "./chunk-XNO6XEWS.mjs";
|
|
4
5
|
import {
|
|
5
6
|
JETTON_REGISTRY,
|
|
6
7
|
USDT_ADDRESSES,
|
|
@@ -11,8 +12,12 @@ import {
|
|
|
11
12
|
getNetworksForJetton,
|
|
12
13
|
getSupportedNetworks,
|
|
13
14
|
getUsdtNetworks,
|
|
14
|
-
isNetworkSupported
|
|
15
|
-
|
|
15
|
+
isNetworkSupported,
|
|
16
|
+
registerExactTonScheme as registerExactTonScheme2
|
|
17
|
+
} from "./chunk-P6JLVB4E.mjs";
|
|
18
|
+
import {
|
|
19
|
+
registerExactTonScheme as registerExactTonScheme3
|
|
20
|
+
} from "./chunk-UB4QVIUC.mjs";
|
|
16
21
|
import {
|
|
17
22
|
DEFAULT_FORWARD_TON,
|
|
18
23
|
DEFAULT_JETTON_TRANSFER_TON,
|
|
@@ -101,6 +106,9 @@ export {
|
|
|
101
106
|
normalizeNetwork,
|
|
102
107
|
parseJettonTransferBody,
|
|
103
108
|
parseTonAddress,
|
|
109
|
+
registerExactTonScheme as registerExactTonClientScheme,
|
|
110
|
+
registerExactTonScheme3 as registerExactTonFacilitatorScheme,
|
|
111
|
+
registerExactTonScheme2 as registerExactTonServerScheme,
|
|
104
112
|
toClientTonSigner,
|
|
105
113
|
toFacilitatorTonSigner,
|
|
106
114
|
validateTonAddress
|