1
1
import { Ton as BaseTon } from '@fireblocks/wallet-derivation' ;
2
- import { ConnectedWallet } from '../ConnectedWallet' ;
3
2
import { TonClient , WalletContractV4 } from '@ton/ton' ;
4
3
import { beginCell , Cell , fromNano } from '@ton/core' ;
5
4
import { AccountData } from '../types' ;
6
5
import { defaultTonWalletV4R2code } from './tonParams' ;
7
6
import axios from 'axios' ;
7
+ import { LateInitConnectedWallet } from '../LateInitConnectedWallet' ;
8
+
9
+ export class Ton extends BaseTon implements LateInitConnectedWallet {
10
+ public memo : string | undefined ;
11
+
12
+ public updateDataEndpoint ( memo ?: string ) : void {
13
+ this . memo = memo ;
14
+ }
15
+
16
+ public getLateInitLabel ( ) : string {
17
+ throw new Error ( 'Method not implemented.' ) ;
18
+ }
8
19
9
- export class Ton extends BaseTon implements ConnectedWallet {
10
20
public rpcURL : string | undefined ;
21
+
11
22
public setRPCUrl ( url : string ) : void {
12
23
this . rpcURL = url ;
13
24
}
14
- private client = new TonClient ( {
15
- endpoint : this . isTestnet ? 'https://testnet.toncenter.com/api/v2/jsonRPC' : 'https://toncenter.com/api/v2/jsonRPC' ,
16
- } ) ;
25
+
26
+ private client : TonClient | undefined ;
27
+
28
+ private init ( ) {
29
+ this . client = new TonClient ( {
30
+ endpoint : this . rpcURL ! ,
31
+ } ) ;
32
+ }
33
+
17
34
private tonWallet = WalletContractV4 . create ( { publicKey : Buffer . from ( this . publicKey . replace ( '0x' , '' ) , 'hex' ) , workchain : 0 } ) ;
18
35
19
36
public async getBalance ( ) : Promise < number > {
20
- await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ;
21
- const contract = this . client . open ( this . tonWallet ) ;
22
- return Number ( fromNano ( await contract . getBalance ( ) ) ) ;
37
+ if ( this . client ) {
38
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ;
39
+ const contract = this . client . open ( this . tonWallet ) ;
40
+ return Number ( fromNano ( await contract . getBalance ( ) ) ) ;
41
+ } else {
42
+ this . relayLogger . error ( 'TON: Client failed to initialize' ) ;
43
+ throw new Error ( 'TON: Client failed to initialize' ) ;
44
+ }
23
45
}
46
+
24
47
public async broadcastTx ( tx : string ) : Promise < string > {
25
48
try {
49
+ // init the TonClient
50
+ this . init ( ) ;
51
+
52
+ // parse the tx back to Ton Cell
26
53
const body = Cell . fromBoc ( Buffer . from ( tx , 'base64' ) ) [ 0 ] ;
27
54
const pubKey = Buffer . from ( this . publicKey . replace ( '0x' , '' ) , 'hex' ) ;
28
-
29
55
const externalMessage = beginCell ( ) . storeUint ( 0b10 , 2 ) . storeUint ( 0 , 2 ) . storeAddress ( this . tonWallet . address ) . storeCoins ( 0 ) ;
30
-
31
56
const seqno = await this . getSeqno ( ) ;
32
57
if ( seqno === 0 ) {
33
58
// for the fist transaction we initialize a state init struct which consists of init struct and code
@@ -40,11 +65,16 @@ export class Ton extends BaseTon implements ConnectedWallet {
40
65
}
41
66
const finalExternalMessage = externalMessage . storeBit ( 1 ) . storeRef ( body ) . endCell ( ) ;
42
67
43
- await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ;
44
- await this . client . sendFile ( finalExternalMessage . toBoc ( ) ) ;
45
- const txHash = finalExternalMessage . hash ( ) . toString ( 'hex' ) ;
46
- this . relayLogger . debug ( `TON: Tx broadcasted: ${ txHash } ` ) ;
47
- return txHash ;
68
+ if ( this . client ) {
69
+ // broadcast Tx and calc TxHash
70
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ;
71
+ await this . client . sendFile ( finalExternalMessage . toBoc ( ) ) ;
72
+ const txHash = finalExternalMessage . hash ( ) . toString ( 'hex' ) ;
73
+ this . relayLogger . debug ( `TON: Tx broadcasted: ${ txHash } ` ) ;
74
+ return txHash ;
75
+ } else {
76
+ throw new Error ( 'TON: Client failed to initialize' ) ;
77
+ }
48
78
} catch ( e ) {
49
79
this . relayLogger . error ( `TON: Error broadcasting tx: ${ e } ` ) ;
50
80
if ( axios . isAxiosError ( e ) ) {
@@ -53,20 +83,25 @@ export class Ton extends BaseTon implements ConnectedWallet {
53
83
throw e ;
54
84
}
55
85
}
86
+
56
87
public async prepare ( ) : Promise < AccountData > {
57
- // get the balance
58
- const balance = await this . getBalance ( ) ; // returned in nanoTon
88
+ // init the TonClient
89
+ this . init ( ) ;
90
+ // get the balance, returned in nanoTon
91
+ const balance = await this . getBalance ( ) ;
59
92
60
93
// fee for regular tx is hardcoded to 0.02 TON
61
94
const feeRate = 0.02 ;
62
- await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
95
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ;
96
+
63
97
// get seqno of the wallet, set it as exrtaParams
64
98
const seqno = await this . getSeqno ( ) ;
65
99
const extraParams = new Map < string , any > ( ) ;
66
100
extraParams . set ( 'seqno' , seqno ) ;
67
101
68
102
const preperedData = {
69
103
balance,
104
+ memo : this . memo ,
70
105
feeRate,
71
106
extraParams,
72
107
insufficientBalance : balance < 0.005 ,
@@ -76,21 +111,20 @@ export class Ton extends BaseTon implements ConnectedWallet {
76
111
}
77
112
private async getSeqno ( ) {
78
113
await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ;
79
- return await this . client . open ( this . tonWallet ) . getSeqno ( ) ;
114
+ return await this . client ! . open ( this . tonWallet ) . getSeqno ( ) ;
80
115
}
81
116
82
117
private createStateInit ( pubKey : Buffer ) {
83
118
// the initial data cell our contract will hold. Wallet V4 has an extra value for plugins in the end
84
119
const dataCell = beginCell ( )
85
120
. storeUint ( 0 , 32 ) // Seqno 0 for the first tx
86
- . storeUint ( 698983191 , 32 ) // Subwallet ID
121
+ . storeUint ( 698983191 , 32 ) // Subwallet ID -> https://docs.ton.org/v3/guidelines/smart-contracts/howto/wallet#subwallet-ids
87
122
. storeBuffer ( pubKey ) // Public Key
88
123
. storeBit ( 0 ) // only for Wallet V4
89
124
. endCell ( ) ;
90
125
91
126
// we take a boiler place already made WalletV4R2 code
92
127
const codeCell = Cell . fromBoc ( Buffer . from ( defaultTonWalletV4R2code , 'base64' ) ) [ 0 ] ;
93
-
94
128
const stateInit = beginCell ( )
95
129
. storeBit ( 0 ) // No split_depth
96
130
. storeBit ( 0 ) // No special
@@ -100,7 +134,6 @@ export class Ton extends BaseTon implements ConnectedWallet {
100
134
. storeRef ( dataCell )
101
135
. storeBit ( 0 ) // No library
102
136
. endCell ( ) ;
103
-
104
137
return stateInit ;
105
138
}
106
139
}
0 commit comments