@anywalletkit/wallet-ton 0.2.3 → 0.2.5
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 +17 -1
- package/dist/index.cjs +121 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +84 -3
- package/dist/index.d.ts +84 -3
- package/dist/index.js +117 -5
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/dist/index.d.cts
CHANGED
|
@@ -218,6 +218,16 @@ declare class UnsafeTransactionError extends SignerError {
|
|
|
218
218
|
readonly code: string;
|
|
219
219
|
constructor(code: string, message: string);
|
|
220
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* `sign()` refused a 32-byte message: the wallet contract checks a transfer's signature over the
|
|
223
|
+
* 32-byte hash of its signing cell, so a signature over 32 raw bytes may authorise one. TON Connect
|
|
224
|
+
* proofs and signData go through `signTonProof` / `signTonConnectData`; transactions through
|
|
225
|
+
* `signTransaction` / `sendTransaction`, where they are reviewed.
|
|
226
|
+
*/
|
|
227
|
+
declare class MessageIsTransactionError extends SignerError {
|
|
228
|
+
readonly code = "message-is-transaction";
|
|
229
|
+
constructor();
|
|
230
|
+
}
|
|
221
231
|
/** Emulation of the external message failed (non-zero compute exit, aborted, action phase failed); nothing was signed or sent. */
|
|
222
232
|
declare class SimulationError extends Error {
|
|
223
233
|
readonly exitCode: number | undefined;
|
|
@@ -617,6 +627,62 @@ declare class WalletAccountReadOnlyTon implements IWalletAccountReadOnly {
|
|
|
617
627
|
verify(message: string | Uint8Array, signature: string): Promise<boolean>;
|
|
618
628
|
}
|
|
619
629
|
|
|
630
|
+
/** What a dApp asks `ton_proof` for: its domain (host), the time of the proof, its nonce. */
|
|
631
|
+
interface TonProofRequest {
|
|
632
|
+
/** The dApp's host as the wallet saw it (`app.example`), never the dApp's own claim. */
|
|
633
|
+
domain: string;
|
|
634
|
+
/** Unix seconds. */
|
|
635
|
+
timestamp: number;
|
|
636
|
+
/** The dApp's `ton_proof` payload. */
|
|
637
|
+
payload: string;
|
|
638
|
+
}
|
|
639
|
+
/** The `proof` object of a TON Connect `ton_proof` reply. */
|
|
640
|
+
interface TonProof {
|
|
641
|
+
timestamp: number;
|
|
642
|
+
domain: {
|
|
643
|
+
lengthBytes: number;
|
|
644
|
+
value: string;
|
|
645
|
+
};
|
|
646
|
+
payload: string;
|
|
647
|
+
/** Base64 ed25519 signature. */
|
|
648
|
+
signature: string;
|
|
649
|
+
}
|
|
650
|
+
/** A `signData` payload. `cell` payloads need schema-aware rendering and are not signed here. */
|
|
651
|
+
type TonSignDataPayload = {
|
|
652
|
+
type: 'text';
|
|
653
|
+
text: string;
|
|
654
|
+
} | {
|
|
655
|
+
type: 'binary';
|
|
656
|
+
bytes: string;
|
|
657
|
+
};
|
|
658
|
+
/** What a dApp asks `signData` for. */
|
|
659
|
+
interface TonSignDataRequest {
|
|
660
|
+
/** The dApp's host as the wallet saw it. */
|
|
661
|
+
domain: string;
|
|
662
|
+
/** Unix seconds. */
|
|
663
|
+
timestamp: number;
|
|
664
|
+
payload: TonSignDataPayload;
|
|
665
|
+
}
|
|
666
|
+
/** The TON Connect `signData` reply. */
|
|
667
|
+
interface TonSignedData {
|
|
668
|
+
/** Base64 ed25519 signature. */
|
|
669
|
+
signature: string;
|
|
670
|
+
/** Raw form (`0:…`) of the address that signed. */
|
|
671
|
+
address: string;
|
|
672
|
+
timestamp: number;
|
|
673
|
+
domain: string;
|
|
674
|
+
payload: TonSignDataPayload;
|
|
675
|
+
}
|
|
676
|
+
/** The address parts the digests bind to. */
|
|
677
|
+
interface TonAddressParts {
|
|
678
|
+
workChain: number;
|
|
679
|
+
hash: Uint8Array;
|
|
680
|
+
}
|
|
681
|
+
/** The 32 bytes a wallet signs for `ton_proof`. */
|
|
682
|
+
declare function tonProofDigest(address: TonAddressParts, request: TonProofRequest): Uint8Array;
|
|
683
|
+
/** The 32 bytes a wallet signs for `signData` (text / binary). */
|
|
684
|
+
declare function tonSignDataDigest(address: TonAddressParts, request: TonSignDataRequest): Uint8Array;
|
|
685
|
+
|
|
620
686
|
/**
|
|
621
687
|
* Signing TON account on Wallet V5R1. It never holds a key: the V5R1 body is
|
|
622
688
|
* signed by `signer.sign(signingCell.hash(), {scheme: 'ed25519', context:
|
|
@@ -642,14 +708,29 @@ declare class WalletAccountTon extends WalletAccountReadOnlyTon implements IWall
|
|
|
642
708
|
static fromPrivateKey(privateKey: Uint8Array, publicKey: Uint8Array, path: string, config?: TonConfig): WalletAccountTon;
|
|
643
709
|
/** Account index for the standard m/44'/607'/i' path. */
|
|
644
710
|
get index(): number | undefined;
|
|
645
|
-
/**
|
|
711
|
+
/**
|
|
712
|
+
* Hex ed25519 signature over the raw message bytes. A 32-byte message — string or bytes — is
|
|
713
|
+
* refused with {@link MessageIsTransactionError}: the wallet contract checks a transfer's
|
|
714
|
+
* signature over the 32-byte hash of its signing cell, so those bytes could be one. Bytes that
|
|
715
|
+
* carry this account's public key are refused as well: one ed25519 key (an external signer) may
|
|
716
|
+
* also be a Solana wallet, and a Solana transaction names its signer's key. TON Connect goes
|
|
717
|
+
* through {@link signTonProof} and {@link signTonConnectData}.
|
|
718
|
+
*/
|
|
646
719
|
sign(message: string | Uint8Array): Promise<string>;
|
|
720
|
+
/**
|
|
721
|
+
* TON Connect `ton_proof` for this wallet's address: the `proof` object of the connect reply. The
|
|
722
|
+
* digest is built here (0xffff ‖ "ton-connect" ‖ …), so no request can turn it into a transfer.
|
|
723
|
+
* `domain` is the host the wallet saw the request come from.
|
|
724
|
+
*/
|
|
725
|
+
signTonProof(request: TonProofRequest): Promise<TonProof>;
|
|
726
|
+
/** TON Connect `signData` (text / binary) for this wallet's address: the reply the dApp gets. */
|
|
727
|
+
signTonConnectData(request: TonSignDataRequest): Promise<TonSignedData>;
|
|
647
728
|
private checkMaxFee;
|
|
648
729
|
/**
|
|
649
730
|
* Checks → seqno → preflight → signed body. The preflight runs on the
|
|
650
731
|
* zero-signed body (ignore_chksig), so nothing is signed before it passes.
|
|
651
732
|
*/
|
|
652
|
-
private
|
|
733
|
+
private signMessages;
|
|
653
734
|
private preflight;
|
|
654
735
|
/** Sign without broadcasting. Returns the external-message BODY as base64 BoC (pass it back to sendTransaction as a Cell). */
|
|
655
736
|
signTransaction(tx: TonSendable, options?: WriteOptions): Promise<string>;
|
|
@@ -701,4 +782,4 @@ declare class WalletManagerTon extends WalletManager<WalletAccountTon, TonConfig
|
|
|
701
782
|
getFeeRates(): Promise<FeeRates>;
|
|
702
783
|
}
|
|
703
784
|
|
|
704
|
-
export { CAIP2, DEFAULT_SEND_MODE, DEFAULT_TONAPI, type DecodedBody, type EmulateOptions, type EmulationOutcome, type EmulationSource, type EmulationVerdict, type GetMethodResult, JETTON_TRANSFER_OP, MAINNET_GLOBAL_ID, MAX_ACTIONS, type ParsedV5R1Body, SEND_MODE, SimulationError, TESTNET_GLOBAL_ID, TON_BASE_PATH, TON_MNEMONIC_PATH, type TonAccountState, type TonAccountStatus, TonCenter, type TonConfig, type TonDescribedKind, type TonDescribedMessage, type TonDescription, type TonEmulateConfig, type TonEndpoint, type TonFees, type TonJettonDetails, type TonProvider, type TonReceipt, type TonRisk, type TonRpc, type TonSendable, type TonSimulation, type TonSimulationSource, type TonTransaction, type TonTransferOptions, type TonWarning, type TonWarningCode, UnsafeTransactionError, type V5R1Message, type V5R1SigningParams, type V5R1WalletIdParts, V5R1_CODE_HEX, V5R1_OP, WalletAccountReadOnlyTon, WalletAccountTon, WalletManagerTon, commentCell, createTonRpc as createTonClient, createTonRpc, decodeBody, WalletManagerTon as default, describeMessageRelaxed, describeTransaction, emulateExternal, emulateViaTonapi, installBufferGlobal, parseEmulation, parseTonapiConsequences, parseTonapiRisk, parseTonapiTrace, parseV5R1Body, resolveEmulate, runEmulation, tonCenterEndpoint, v5r1Address, v5r1Code, v5r1ExternalMessage, v5r1PackSigned, v5r1PackUnsigned, v5r1SigningMessage, v5r1StateInit, v5r1WalletId };
|
|
785
|
+
export { CAIP2, DEFAULT_SEND_MODE, DEFAULT_TONAPI, type DecodedBody, type EmulateOptions, type EmulationOutcome, type EmulationSource, type EmulationVerdict, type GetMethodResult, JETTON_TRANSFER_OP, MAINNET_GLOBAL_ID, MAX_ACTIONS, MessageIsTransactionError, type ParsedV5R1Body, SEND_MODE, SimulationError, TESTNET_GLOBAL_ID, TON_BASE_PATH, TON_MNEMONIC_PATH, type TonAccountState, type TonAccountStatus, type TonAddressParts, TonCenter, type TonConfig, type TonDescribedKind, type TonDescribedMessage, type TonDescription, type TonEmulateConfig, type TonEndpoint, type TonFees, type TonJettonDetails, type TonProof, type TonProofRequest, type TonProvider, type TonReceipt, type TonRisk, type TonRpc, type TonSendable, type TonSignDataPayload, type TonSignDataRequest, type TonSignedData, type TonSimulation, type TonSimulationSource, type TonTransaction, type TonTransferOptions, type TonWarning, type TonWarningCode, UnsafeTransactionError, type V5R1Message, type V5R1SigningParams, type V5R1WalletIdParts, V5R1_CODE_HEX, V5R1_OP, WalletAccountReadOnlyTon, WalletAccountTon, WalletManagerTon, commentCell, createTonRpc as createTonClient, createTonRpc, decodeBody, WalletManagerTon as default, describeMessageRelaxed, describeTransaction, emulateExternal, emulateViaTonapi, installBufferGlobal, parseEmulation, parseTonapiConsequences, parseTonapiRisk, parseTonapiTrace, parseV5R1Body, resolveEmulate, runEmulation, tonCenterEndpoint, tonProofDigest, tonSignDataDigest, v5r1Address, v5r1Code, v5r1ExternalMessage, v5r1PackSigned, v5r1PackUnsigned, v5r1SigningMessage, v5r1StateInit, v5r1WalletId };
|
package/dist/index.d.ts
CHANGED
|
@@ -218,6 +218,16 @@ declare class UnsafeTransactionError extends SignerError {
|
|
|
218
218
|
readonly code: string;
|
|
219
219
|
constructor(code: string, message: string);
|
|
220
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* `sign()` refused a 32-byte message: the wallet contract checks a transfer's signature over the
|
|
223
|
+
* 32-byte hash of its signing cell, so a signature over 32 raw bytes may authorise one. TON Connect
|
|
224
|
+
* proofs and signData go through `signTonProof` / `signTonConnectData`; transactions through
|
|
225
|
+
* `signTransaction` / `sendTransaction`, where they are reviewed.
|
|
226
|
+
*/
|
|
227
|
+
declare class MessageIsTransactionError extends SignerError {
|
|
228
|
+
readonly code = "message-is-transaction";
|
|
229
|
+
constructor();
|
|
230
|
+
}
|
|
221
231
|
/** Emulation of the external message failed (non-zero compute exit, aborted, action phase failed); nothing was signed or sent. */
|
|
222
232
|
declare class SimulationError extends Error {
|
|
223
233
|
readonly exitCode: number | undefined;
|
|
@@ -617,6 +627,62 @@ declare class WalletAccountReadOnlyTon implements IWalletAccountReadOnly {
|
|
|
617
627
|
verify(message: string | Uint8Array, signature: string): Promise<boolean>;
|
|
618
628
|
}
|
|
619
629
|
|
|
630
|
+
/** What a dApp asks `ton_proof` for: its domain (host), the time of the proof, its nonce. */
|
|
631
|
+
interface TonProofRequest {
|
|
632
|
+
/** The dApp's host as the wallet saw it (`app.example`), never the dApp's own claim. */
|
|
633
|
+
domain: string;
|
|
634
|
+
/** Unix seconds. */
|
|
635
|
+
timestamp: number;
|
|
636
|
+
/** The dApp's `ton_proof` payload. */
|
|
637
|
+
payload: string;
|
|
638
|
+
}
|
|
639
|
+
/** The `proof` object of a TON Connect `ton_proof` reply. */
|
|
640
|
+
interface TonProof {
|
|
641
|
+
timestamp: number;
|
|
642
|
+
domain: {
|
|
643
|
+
lengthBytes: number;
|
|
644
|
+
value: string;
|
|
645
|
+
};
|
|
646
|
+
payload: string;
|
|
647
|
+
/** Base64 ed25519 signature. */
|
|
648
|
+
signature: string;
|
|
649
|
+
}
|
|
650
|
+
/** A `signData` payload. `cell` payloads need schema-aware rendering and are not signed here. */
|
|
651
|
+
type TonSignDataPayload = {
|
|
652
|
+
type: 'text';
|
|
653
|
+
text: string;
|
|
654
|
+
} | {
|
|
655
|
+
type: 'binary';
|
|
656
|
+
bytes: string;
|
|
657
|
+
};
|
|
658
|
+
/** What a dApp asks `signData` for. */
|
|
659
|
+
interface TonSignDataRequest {
|
|
660
|
+
/** The dApp's host as the wallet saw it. */
|
|
661
|
+
domain: string;
|
|
662
|
+
/** Unix seconds. */
|
|
663
|
+
timestamp: number;
|
|
664
|
+
payload: TonSignDataPayload;
|
|
665
|
+
}
|
|
666
|
+
/** The TON Connect `signData` reply. */
|
|
667
|
+
interface TonSignedData {
|
|
668
|
+
/** Base64 ed25519 signature. */
|
|
669
|
+
signature: string;
|
|
670
|
+
/** Raw form (`0:…`) of the address that signed. */
|
|
671
|
+
address: string;
|
|
672
|
+
timestamp: number;
|
|
673
|
+
domain: string;
|
|
674
|
+
payload: TonSignDataPayload;
|
|
675
|
+
}
|
|
676
|
+
/** The address parts the digests bind to. */
|
|
677
|
+
interface TonAddressParts {
|
|
678
|
+
workChain: number;
|
|
679
|
+
hash: Uint8Array;
|
|
680
|
+
}
|
|
681
|
+
/** The 32 bytes a wallet signs for `ton_proof`. */
|
|
682
|
+
declare function tonProofDigest(address: TonAddressParts, request: TonProofRequest): Uint8Array;
|
|
683
|
+
/** The 32 bytes a wallet signs for `signData` (text / binary). */
|
|
684
|
+
declare function tonSignDataDigest(address: TonAddressParts, request: TonSignDataRequest): Uint8Array;
|
|
685
|
+
|
|
620
686
|
/**
|
|
621
687
|
* Signing TON account on Wallet V5R1. It never holds a key: the V5R1 body is
|
|
622
688
|
* signed by `signer.sign(signingCell.hash(), {scheme: 'ed25519', context:
|
|
@@ -642,14 +708,29 @@ declare class WalletAccountTon extends WalletAccountReadOnlyTon implements IWall
|
|
|
642
708
|
static fromPrivateKey(privateKey: Uint8Array, publicKey: Uint8Array, path: string, config?: TonConfig): WalletAccountTon;
|
|
643
709
|
/** Account index for the standard m/44'/607'/i' path. */
|
|
644
710
|
get index(): number | undefined;
|
|
645
|
-
/**
|
|
711
|
+
/**
|
|
712
|
+
* Hex ed25519 signature over the raw message bytes. A 32-byte message — string or bytes — is
|
|
713
|
+
* refused with {@link MessageIsTransactionError}: the wallet contract checks a transfer's
|
|
714
|
+
* signature over the 32-byte hash of its signing cell, so those bytes could be one. Bytes that
|
|
715
|
+
* carry this account's public key are refused as well: one ed25519 key (an external signer) may
|
|
716
|
+
* also be a Solana wallet, and a Solana transaction names its signer's key. TON Connect goes
|
|
717
|
+
* through {@link signTonProof} and {@link signTonConnectData}.
|
|
718
|
+
*/
|
|
646
719
|
sign(message: string | Uint8Array): Promise<string>;
|
|
720
|
+
/**
|
|
721
|
+
* TON Connect `ton_proof` for this wallet's address: the `proof` object of the connect reply. The
|
|
722
|
+
* digest is built here (0xffff ‖ "ton-connect" ‖ …), so no request can turn it into a transfer.
|
|
723
|
+
* `domain` is the host the wallet saw the request come from.
|
|
724
|
+
*/
|
|
725
|
+
signTonProof(request: TonProofRequest): Promise<TonProof>;
|
|
726
|
+
/** TON Connect `signData` (text / binary) for this wallet's address: the reply the dApp gets. */
|
|
727
|
+
signTonConnectData(request: TonSignDataRequest): Promise<TonSignedData>;
|
|
647
728
|
private checkMaxFee;
|
|
648
729
|
/**
|
|
649
730
|
* Checks → seqno → preflight → signed body. The preflight runs on the
|
|
650
731
|
* zero-signed body (ignore_chksig), so nothing is signed before it passes.
|
|
651
732
|
*/
|
|
652
|
-
private
|
|
733
|
+
private signMessages;
|
|
653
734
|
private preflight;
|
|
654
735
|
/** Sign without broadcasting. Returns the external-message BODY as base64 BoC (pass it back to sendTransaction as a Cell). */
|
|
655
736
|
signTransaction(tx: TonSendable, options?: WriteOptions): Promise<string>;
|
|
@@ -701,4 +782,4 @@ declare class WalletManagerTon extends WalletManager<WalletAccountTon, TonConfig
|
|
|
701
782
|
getFeeRates(): Promise<FeeRates>;
|
|
702
783
|
}
|
|
703
784
|
|
|
704
|
-
export { CAIP2, DEFAULT_SEND_MODE, DEFAULT_TONAPI, type DecodedBody, type EmulateOptions, type EmulationOutcome, type EmulationSource, type EmulationVerdict, type GetMethodResult, JETTON_TRANSFER_OP, MAINNET_GLOBAL_ID, MAX_ACTIONS, type ParsedV5R1Body, SEND_MODE, SimulationError, TESTNET_GLOBAL_ID, TON_BASE_PATH, TON_MNEMONIC_PATH, type TonAccountState, type TonAccountStatus, TonCenter, type TonConfig, type TonDescribedKind, type TonDescribedMessage, type TonDescription, type TonEmulateConfig, type TonEndpoint, type TonFees, type TonJettonDetails, type TonProvider, type TonReceipt, type TonRisk, type TonRpc, type TonSendable, type TonSimulation, type TonSimulationSource, type TonTransaction, type TonTransferOptions, type TonWarning, type TonWarningCode, UnsafeTransactionError, type V5R1Message, type V5R1SigningParams, type V5R1WalletIdParts, V5R1_CODE_HEX, V5R1_OP, WalletAccountReadOnlyTon, WalletAccountTon, WalletManagerTon, commentCell, createTonRpc as createTonClient, createTonRpc, decodeBody, WalletManagerTon as default, describeMessageRelaxed, describeTransaction, emulateExternal, emulateViaTonapi, installBufferGlobal, parseEmulation, parseTonapiConsequences, parseTonapiRisk, parseTonapiTrace, parseV5R1Body, resolveEmulate, runEmulation, tonCenterEndpoint, v5r1Address, v5r1Code, v5r1ExternalMessage, v5r1PackSigned, v5r1PackUnsigned, v5r1SigningMessage, v5r1StateInit, v5r1WalletId };
|
|
785
|
+
export { CAIP2, DEFAULT_SEND_MODE, DEFAULT_TONAPI, type DecodedBody, type EmulateOptions, type EmulationOutcome, type EmulationSource, type EmulationVerdict, type GetMethodResult, JETTON_TRANSFER_OP, MAINNET_GLOBAL_ID, MAX_ACTIONS, MessageIsTransactionError, type ParsedV5R1Body, SEND_MODE, SimulationError, TESTNET_GLOBAL_ID, TON_BASE_PATH, TON_MNEMONIC_PATH, type TonAccountState, type TonAccountStatus, type TonAddressParts, TonCenter, type TonConfig, type TonDescribedKind, type TonDescribedMessage, type TonDescription, type TonEmulateConfig, type TonEndpoint, type TonFees, type TonJettonDetails, type TonProof, type TonProofRequest, type TonProvider, type TonReceipt, type TonRisk, type TonRpc, type TonSendable, type TonSignDataPayload, type TonSignDataRequest, type TonSignedData, type TonSimulation, type TonSimulationSource, type TonTransaction, type TonTransferOptions, type TonWarning, type TonWarningCode, UnsafeTransactionError, type V5R1Message, type V5R1SigningParams, type V5R1WalletIdParts, V5R1_CODE_HEX, V5R1_OP, WalletAccountReadOnlyTon, WalletAccountTon, WalletManagerTon, commentCell, createTonRpc as createTonClient, createTonRpc, decodeBody, WalletManagerTon as default, describeMessageRelaxed, describeTransaction, emulateExternal, emulateViaTonapi, installBufferGlobal, parseEmulation, parseTonapiConsequences, parseTonapiRisk, parseTonapiTrace, parseV5R1Body, resolveEmulate, runEmulation, tonCenterEndpoint, tonProofDigest, tonSignDataDigest, v5r1Address, v5r1Code, v5r1ExternalMessage, v5r1PackSigned, v5r1PackUnsigned, v5r1SigningMessage, v5r1StateInit, v5r1WalletId };
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,13 @@ var UnsafeTransactionError = class extends SignerError {
|
|
|
30
30
|
this.code = code;
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
|
+
var MessageIsTransactionError = class extends SignerError {
|
|
34
|
+
code = "message-is-transaction";
|
|
35
|
+
constructor() {
|
|
36
|
+
super("This message has the shape of a transaction (a 32-byte TON hash, or bytes naming this key as a Solana signer) and is not signed; use signTonProof / signTonConnectData for TON Connect, or signTransaction so it can be reviewed.");
|
|
37
|
+
this.name = "MessageIsTransactionError";
|
|
38
|
+
}
|
|
39
|
+
};
|
|
33
40
|
var SimulationError = class extends Error {
|
|
34
41
|
exitCode;
|
|
35
42
|
aborted;
|
|
@@ -935,8 +942,75 @@ function randomQueryId() {
|
|
|
935
942
|
|
|
936
943
|
// src/account.ts
|
|
937
944
|
import { LocalSigner, feeLimit, requireCurve } from "@anywalletkit/core";
|
|
945
|
+
import { Buffer as Buffer5 } from "buffer";
|
|
938
946
|
import { Cell as Cell5 } from "@ton/core";
|
|
947
|
+
|
|
948
|
+
// src/tonconnect.ts
|
|
949
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
950
|
+
import { Buffer as Buffer4 } from "buffer";
|
|
951
|
+
var utf82 = (s) => new TextEncoder().encode(s);
|
|
952
|
+
var int32BE = (n) => {
|
|
953
|
+
const b = new Uint8Array(4);
|
|
954
|
+
new DataView(b.buffer).setInt32(0, n, false);
|
|
955
|
+
return b;
|
|
956
|
+
};
|
|
957
|
+
var uint32 = (n, littleEndian) => {
|
|
958
|
+
const b = new Uint8Array(4);
|
|
959
|
+
new DataView(b.buffer).setUint32(0, n, littleEndian);
|
|
960
|
+
return b;
|
|
961
|
+
};
|
|
962
|
+
var uint64 = (n, littleEndian) => {
|
|
963
|
+
const b = new Uint8Array(8);
|
|
964
|
+
new DataView(b.buffer).setBigUint64(0, BigInt(n), littleEndian);
|
|
965
|
+
return b;
|
|
966
|
+
};
|
|
967
|
+
var concat = (...parts) => {
|
|
968
|
+
const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0));
|
|
969
|
+
let o = 0;
|
|
970
|
+
for (const p of parts) {
|
|
971
|
+
out.set(p, o);
|
|
972
|
+
o += p.length;
|
|
973
|
+
}
|
|
974
|
+
return out;
|
|
975
|
+
};
|
|
976
|
+
function checkCommon(address, domain, timestamp) {
|
|
977
|
+
if (address.hash.length !== 32) throw new RangeError("TON address hash must be 32 bytes.");
|
|
978
|
+
if (!Number.isInteger(address.workChain)) throw new TypeError("TON address workChain must be an integer.");
|
|
979
|
+
if (typeof domain !== "string" || domain.length === 0) throw new TypeError("TON Connect domain must be a non-empty string.");
|
|
980
|
+
if (typeof timestamp !== "number" || !Number.isSafeInteger(timestamp) || timestamp < 0) throw new TypeError("TON Connect timestamp must be a non-negative integer (unix seconds).");
|
|
981
|
+
}
|
|
982
|
+
function base64Bytes(raw) {
|
|
983
|
+
const s = raw.replace(/[\t\n\f\r ]/g, "");
|
|
984
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(s) || s.replace(/=+$/, "").length % 4 === 1) throw new TypeError("signData binary payload must be base64.");
|
|
985
|
+
return new Uint8Array(Buffer4.from(s, "base64"));
|
|
986
|
+
}
|
|
987
|
+
function tonProofDigest(address, request) {
|
|
988
|
+
checkCommon(address, request.domain, request.timestamp);
|
|
989
|
+
if (typeof request.payload !== "string") throw new TypeError("ton_proof payload must be a string.");
|
|
990
|
+
const domain = utf82(request.domain);
|
|
991
|
+
const inner = concat(utf82("ton-proof-item-v2/"), int32BE(address.workChain), address.hash, uint32(domain.length, true), domain, uint64(request.timestamp, true), utf82(request.payload));
|
|
992
|
+
return sha256(concat(new Uint8Array([255, 255]), utf82("ton-connect"), sha256(inner)));
|
|
993
|
+
}
|
|
994
|
+
function tonSignDataDigest(address, request) {
|
|
995
|
+
checkCommon(address, request.domain, request.timestamp);
|
|
996
|
+
const p = request.payload;
|
|
997
|
+
let payload;
|
|
998
|
+
if (p?.type === "text" && typeof p.text === "string") payload = utf82(p.text);
|
|
999
|
+
else if (p?.type === "binary" && typeof p.bytes === "string") payload = base64Bytes(p.bytes);
|
|
1000
|
+
else throw new TypeError('signData payload must be { type: "text", text } or { type: "binary", bytes }; cell payloads are not supported.');
|
|
1001
|
+
const domain = utf82(request.domain);
|
|
1002
|
+
return sha256(concat(new Uint8Array([255, 255]), utf82("ton-connect/sign-data/"), int32BE(address.workChain), address.hash, uint32(domain.length, false), domain, uint64(request.timestamp, false), utf82(p.type === "text" ? "txt" : "bin"), uint32(payload.length, false), payload));
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
// src/account.ts
|
|
939
1006
|
var toHex = (u8) => Array.from(u8, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
1007
|
+
var carriesKey = (bytes, key) => {
|
|
1008
|
+
outer: for (let i = 0; i + key.length <= bytes.length; i++) {
|
|
1009
|
+
for (let j = 0; j < key.length; j++) if (bytes[i + j] !== key[j]) continue outer;
|
|
1010
|
+
return true;
|
|
1011
|
+
}
|
|
1012
|
+
return false;
|
|
1013
|
+
};
|
|
940
1014
|
var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon {
|
|
941
1015
|
/** seqno and fees come from the network before signing. */
|
|
942
1016
|
needsNetwork = true;
|
|
@@ -960,11 +1034,46 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
|
|
|
960
1034
|
const m = /^m\/44'\/607'\/(\d+)'$/.exec(this.path);
|
|
961
1035
|
return m ? Number(m[1]) : void 0;
|
|
962
1036
|
}
|
|
963
|
-
/**
|
|
1037
|
+
/**
|
|
1038
|
+
* Hex ed25519 signature over the raw message bytes. A 32-byte message — string or bytes — is
|
|
1039
|
+
* refused with {@link MessageIsTransactionError}: the wallet contract checks a transfer's
|
|
1040
|
+
* signature over the 32-byte hash of its signing cell, so those bytes could be one. Bytes that
|
|
1041
|
+
* carry this account's public key are refused as well: one ed25519 key (an external signer) may
|
|
1042
|
+
* also be a Solana wallet, and a Solana transaction names its signer's key. TON Connect goes
|
|
1043
|
+
* through {@link signTonProof} and {@link signTonConnectData}.
|
|
1044
|
+
*/
|
|
964
1045
|
async sign(message) {
|
|
965
1046
|
const bytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
1047
|
+
if (bytes.length === 32 || carriesKey(bytes, this.publicKey)) throw new MessageIsTransactionError();
|
|
966
1048
|
return toHex(await this.signer.sign(bytes, { scheme: "ed25519", context: "ton-message" }));
|
|
967
1049
|
}
|
|
1050
|
+
/**
|
|
1051
|
+
* TON Connect `ton_proof` for this wallet's address: the `proof` object of the connect reply. The
|
|
1052
|
+
* digest is built here (0xffff ‖ "ton-connect" ‖ …), so no request can turn it into a transfer.
|
|
1053
|
+
* `domain` is the host the wallet saw the request come from.
|
|
1054
|
+
*/
|
|
1055
|
+
async signTonProof(request) {
|
|
1056
|
+
const digest = tonProofDigest(this._address, request);
|
|
1057
|
+
const signature = await this.signer.sign(digest, { scheme: "ed25519", context: "ton-proof" });
|
|
1058
|
+
return {
|
|
1059
|
+
timestamp: request.timestamp,
|
|
1060
|
+
domain: { lengthBytes: new TextEncoder().encode(request.domain).length, value: request.domain },
|
|
1061
|
+
payload: request.payload,
|
|
1062
|
+
signature: Buffer5.from(signature).toString("base64")
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
/** TON Connect `signData` (text / binary) for this wallet's address: the reply the dApp gets. */
|
|
1066
|
+
async signTonConnectData(request) {
|
|
1067
|
+
const digest = tonSignDataDigest(this._address, request);
|
|
1068
|
+
const signature = await this.signer.sign(digest, { scheme: "ed25519", context: "ton-sign-data" });
|
|
1069
|
+
return {
|
|
1070
|
+
signature: Buffer5.from(signature).toString("base64"),
|
|
1071
|
+
address: this._address.toRawString(),
|
|
1072
|
+
timestamp: request.timestamp,
|
|
1073
|
+
domain: request.domain,
|
|
1074
|
+
payload: request.payload.type === "text" ? { type: "text", text: request.payload.text } : { type: "binary", bytes: request.payload.bytes }
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
968
1077
|
checkMaxFee(fee, limit, op) {
|
|
969
1078
|
if (limit !== void 0 && fee > BigInt(limit)) throw new Error(`Exceeded maximum fee cost for ${op} operation.`);
|
|
970
1079
|
}
|
|
@@ -972,7 +1081,7 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
|
|
|
972
1081
|
* Checks → seqno → preflight → signed body. The preflight runs on the
|
|
973
1082
|
* zero-signed body (ignore_chksig), so nothing is signed before it passes.
|
|
974
1083
|
*/
|
|
975
|
-
async
|
|
1084
|
+
async signMessages(messages, limit, op) {
|
|
976
1085
|
const want = messages.reduce((sum, m) => sum + (m.message.info.type === "internal" ? m.message.info.value.coins : 0n), 0n);
|
|
977
1086
|
if (want > 0n) {
|
|
978
1087
|
const balance = await this.getBalance();
|
|
@@ -1007,7 +1116,7 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
|
|
|
1007
1116
|
await this.preflight(tx, feeLimit(this._config.transactionMaxFee, options), "transaction");
|
|
1008
1117
|
return tx.toBoc().toString("base64");
|
|
1009
1118
|
}
|
|
1010
|
-
const { body } = await this.
|
|
1119
|
+
const { body } = await this.signMessages(this.toMessages(tx), feeLimit(this._config.transactionMaxFee, options), "transaction");
|
|
1011
1120
|
return body.toBoc().toString("base64");
|
|
1012
1121
|
}
|
|
1013
1122
|
async broadcast(body) {
|
|
@@ -1019,14 +1128,14 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
|
|
|
1019
1128
|
/** Sign and broadcast; `hash` is the body hash (hex) — resolve it with getTransactionReceipt. */
|
|
1020
1129
|
async sendTransaction(tx, options = {}) {
|
|
1021
1130
|
this.requireRpc("send transactions");
|
|
1022
|
-
const { body, fee } = tx instanceof Cell5 ? { body: tx, fee: await this.preflight(tx, feeLimit(this._config.transactionMaxFee, options), "transaction") } : await this.
|
|
1131
|
+
const { body, fee } = tx instanceof Cell5 ? { body: tx, fee: await this.preflight(tx, feeLimit(this._config.transactionMaxFee, options), "transaction") } : await this.signMessages(this.toMessages(tx), feeLimit(this._config.transactionMaxFee, options), "transaction");
|
|
1023
1132
|
return { hash: await this.broadcast(body), fee };
|
|
1024
1133
|
}
|
|
1025
1134
|
/** TON (no `token`) or jetton transfer. */
|
|
1026
1135
|
async transfer(o, writeOptions = {}) {
|
|
1027
1136
|
this.requireRpc("transfer tokens");
|
|
1028
1137
|
const message = o.token ? await this.jettonTransferMessage(o) : this.transactionMessage({ to: o.recipient, value: o.amount, ...o.memo !== void 0 ? { body: o.memo } : {} });
|
|
1029
|
-
const { body, fee } = await this.
|
|
1138
|
+
const { body, fee } = await this.signMessages([message], feeLimit(this._config.transferMaxFee, writeOptions), "transfer");
|
|
1030
1139
|
return { hash: await this.broadcast(body), fee };
|
|
1031
1140
|
}
|
|
1032
1141
|
/** The same wallet as a {@link WalletAccountReadOnlyTon}. */
|
|
@@ -1130,6 +1239,7 @@ export {
|
|
|
1130
1239
|
JETTON_TRANSFER_OP,
|
|
1131
1240
|
MAINNET_GLOBAL_ID,
|
|
1132
1241
|
MAX_ACTIONS,
|
|
1242
|
+
MessageIsTransactionError,
|
|
1133
1243
|
SEND_MODE,
|
|
1134
1244
|
SimulationError,
|
|
1135
1245
|
TESTNET_GLOBAL_ID,
|
|
@@ -1168,6 +1278,8 @@ export {
|
|
|
1168
1278
|
runEmulation,
|
|
1169
1279
|
tonCenterEndpoint,
|
|
1170
1280
|
tonExplorerTxUrl,
|
|
1281
|
+
tonProofDigest,
|
|
1282
|
+
tonSignDataDigest,
|
|
1171
1283
|
v5r1Address,
|
|
1172
1284
|
v5r1Code,
|
|
1173
1285
|
v5r1ExternalMessage,
|