turing-wallet-provider 1.5.2 → 1.5.4

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 CHANGED
@@ -65,6 +65,71 @@ const {name,platform,version} = await wallet.getInfo();
65
65
  {Turing,android,1.0.0}//示例的返回值
66
66
  ```
67
67
 
68
+ ## getNetwork
69
+
70
+ 获取已连接账户当前激活的网络。
71
+
72
+ ### 用法
73
+
74
+ ```ts
75
+ const wallet = useTuringWallet();
76
+ const network = await wallet.getNetwork();
77
+ ```
78
+
79
+ ### 参数
80
+
81
+ 该方法不接受任何参数。
82
+
83
+ ### 返回值
84
+
85
+ ```ts
86
+ interface GetNetworkResponse {
87
+ network: "tbc" | "btc" | "eth" | "bnb" | "all";
88
+ type: "mainnet" | "testnet";
89
+ }
90
+ ```
91
+
92
+ | 字段 | 类型 | 说明 |
93
+ | --- | --- | --- |
94
+ | `network` | `"tbc" \| "btc" \| "eth" \| "bnb" \| "all"` | 当前激活的链。`"all"` 表示用户处于钱包的"所有网络"视图,未选择具体的链。 |
95
+ | `type` | `"mainnet" \| "testnet"` | 主网 / 测试网。仅 `tbc` 可能为 `"testnet"`,其余链恒为 `"mainnet"`。 |
96
+
97
+ ### 错误处理
98
+
99
+ | 错误 | 原因 |
100
+ | --- | --- |
101
+ | `User not connected` | 尚未调用 `wallet.connect()`,或用户已断开连接。 |
102
+
103
+ ```ts
104
+ const wallet = useTuringWallet();
105
+
106
+ try {
107
+ const info = await wallet.getNetwork();
108
+ console.log(info);
109
+ } catch (error) {
110
+ console.error("Failed to get network:", error);
111
+ }
112
+ ```
113
+
114
+ ### 订阅变化
115
+
116
+ 钱包内切换网络时,dapp 会收到 `TuringNetworkChanged` 事件并附带新的网络信息,无需轮询 `getNetwork()`。
117
+
118
+ ```ts
119
+ window.addEventListener("TuringNetworkChanged", (event) => {
120
+ const { network } = event.detail;
121
+ // `network` 与 wallet.getNetwork() 的返回值同结构
122
+ });
123
+ ```
124
+
125
+ ```ts
126
+ interface TuringNetworkChangedDetail {
127
+ network: GetNetworkResponse;
128
+ }
129
+ ```
130
+
131
+ 仅在 dapp 已连接期间触发,且只推送 `connect()` 之后的变化(初始网络可通过 `wallet.getNetwork()` 获取)。
132
+
68
133
  ## signMessage
69
134
 
70
135
  ```ts
@@ -176,33 +241,93 @@ broadcastTXsraw(txs.map((tx) => ({ txraw: tx.uncheckedSerialize() })));
176
241
 
177
242
  ## signAssociatedTransaction
178
243
 
244
+ 使用钱包签名父子(关联)交易。钱包根据源交易构建子交易并统一签名。
245
+
246
+ ### 用法
247
+
248
+ ```ts
249
+ const { txraws } = await Turing.signAssociatedTransaction({
250
+ sourceTxraw,
251
+ sourceUtxos,
252
+ inputs,
253
+ outputs,
254
+ });
255
+ ```
256
+
257
+ ### 参数
258
+
179
259
  ```ts
180
- //使用示例
181
260
  interface Input {
182
- txId?: string;
183
- script?: string; //仅支持hex类型,不支持asm
184
- satoshis?: number;
185
- outputIndex: number;
186
- scriptSigType: "p2pkh" | "tbc20" | "tbc20_contract" | "other";
187
- unfinishedScriptSig?: string; // 对于"other"类型,用于提供自定义脚本(不包含交易数据的锁定脚本)模板,仅支持hex类型,不支持asm。签名部分用097369676e6174757265替代,09为7369676e6174757265长度
188
- ftVersion?: 1 | 2; // 对于"tbc20_contract"类型,FT版本(1或2)
189
- contractTxId?: string; // 对于"tbc20_contract"类型,合约交易ID
261
+ txId?: string; // 交易 ID(源交易输入需提供)
262
+ script?: string; // 锁定脚本,仅支持 hex 格式
263
+ satoshis?: number; // satoshi 值
264
+ outputIndex: number; // 输出索引
265
+ scriptSigType:
266
+ | "p2pkh"
267
+ | "tbc20" // 普通 FT 转账解锁
268
+ | "tbc20_contract" // 普通 FT 在合约/swap 场景下的解锁
269
+ | "tbc20_coin" // 稳定币转账解锁(FT.getFTunlock + isCoin)
270
+ | "tbc20_coin_contract" // 稳定币在合约/swap 场景下的解锁(FT.getFTunlockSwap + isCoin)
271
+ | "other"; // 脚本签名类型
272
+ unfinishedScriptSig?: string; // "other" 类型的自定义脚本模板(hex 格式),签名部分用 097369676e6174757265 替代
273
+ ftVersion?: 1 | 2; // "tbc20_contract"/"tbc20_coin_contract" 类型的 FT 版本
274
+ contractTxId?: string; // "tbc20_contract"/"tbc20_coin_contract" 类型的合约交易 ID
190
275
  }
191
276
 
192
277
  interface Output {
193
- script: string; //仅支持hex类型,不支持asm
194
- satoshis: number;
278
+ script: string; // 输出锁定脚本,仅支持 hex 格式
279
+ satoshis: number; // 输出的 satoshi 值
195
280
  }
196
281
 
197
282
  interface SignAssociatedTransactionRequestData {
198
- sourceTxraw: string;
199
- sourceUtxos: Input[];
200
- inputs?: Input[][];
201
- outputs?: Output[][];
283
+ sourceTxraw: string; // 源头交易的原始 hex 字符串
284
+ sourceUtxos: Input[]; // 源头交易的 UTXO 数组
285
+ inputs?: Input[][]; // 子交易输入的二维数组
286
+ outputs?: Output[][]; // 子交易输出的二维数组
287
+ }
288
+ ```
289
+
290
+ | 参数 | 类型 | 必填 | 说明 |
291
+ | --- | --- | --- | --- |
292
+ | `sourceTxraw` | `string` | 是 | 源头交易的原始 hex 字符串 |
293
+ | `sourceUtxos` | `Input[]` | 是 | 源头交易的 UTXO 数组 |
294
+ | `inputs` | `Input[][]` | 否 | 二维数组 — 每个子数组代表一个子交易的输入 |
295
+ | `outputs` | `Output[][]` | 否 | 二维数组 — 每个子数组代表一个子交易的输出 |
296
+
297
+ ### 返回值
298
+
299
+ ```ts
300
+ interface SignAssociatedTransactionResponse {
301
+ txraws: string[]; // 已组装的待广播交易 hex 字符串数组(包含父子交易)
302
+ }
303
+ ```
304
+
305
+ | 字段 | 类型 | 说明 |
306
+ | --- | --- | --- |
307
+ | `txraws` | `string[]` | 包含父子交易的已组装待广播交易数组 |
308
+
309
+ ### 错误处理
310
+
311
+ ```ts
312
+ try {
313
+ const { txraws } = await Turing.signAssociatedTransaction({
314
+ sourceTxraw,
315
+ sourceUtxos,
316
+ inputs,
317
+ outputs,
318
+ });
319
+ console.log("交易:", txraws);
320
+ } catch (error) {
321
+ console.error("签名失败:", error);
202
322
  }
323
+ ```
324
+
325
+ ### 示例
203
326
 
204
- //ft转移示例参数
205
- const sourceUtxos: intput[] = [
327
+ FT 转移示例:
328
+
329
+ ```ts
330
+ const sourceUtxos: Input[] = [
206
331
  {
207
332
  txId: "",
208
333
  outputIndex: 0,
@@ -219,7 +344,7 @@ const sourceUtxos: intput[] = [
219
344
  },
220
345
  ];
221
346
 
222
- const inputs: intput[][] = [
347
+ const inputs: Input[][] = [
223
348
  [
224
349
  { outputIndex: 0, scriptSigType: "tbc20" },
225
350
  { outputIndex: 2, scriptSigType: "p2pkh" },
@@ -230,7 +355,7 @@ const inputs: intput[][] = [
230
355
  ],
231
356
  ];
232
357
 
233
- const outputs: output[][] = [
358
+ const outputs: Output[][] = [
234
359
  [
235
360
  {
236
361
  script: ftcode,
@@ -261,8 +386,113 @@ const outputs: output[][] = [
261
386
  ],
262
387
  ];
263
388
 
264
- const wallet = useTuringWallet();
265
- const { txraws } = await wallet.signAssociatedTransaction(params);
389
+ const { txraws } = await Turing.signAssociatedTransaction({
390
+ sourceTxraw,
391
+ sourceUtxos,
392
+ inputs,
393
+ outputs,
394
+ });
395
+ ```
396
+
397
+ ### 稳定币 (tbc20_coin / tbc20_coin_contract)
398
+
399
+ 稳定币是一种特殊的 FT,解锁脚本与普通 FT 不同,所以提供了专用的 `scriptSigType`:
400
+
401
+ - `"tbc20_coin"`:稳定币普通转账解锁
402
+ - `"tbc20_coin_contract"`:稳定币参与合约 / swap 场景的解锁(同时需要 `contractTxId` 与 `ftVersion`)
403
+
404
+ #### 子交易 (`inputs` / `outputs`)
405
+
406
+ 只要把对应输入的 `scriptSigType` 标成 `"tbc20_coin"` 或 `"tbc20_coin_contract"` 即可,**其它字段与普通 FT 写法完全一致**,无需关心 sequence / nLockTime。
407
+
408
+ #### 源交易 (`sourceTxraw`)
409
+
410
+ `sourceTxraw` 是调用方自己组装好的原始交易,**如果里面包含稳定币输入**,必须在构建时自行满足以下两个条件:
411
+
412
+ 1. 每个稳定币输入的 `sequence` 设为 `0xFFFFFFFE`
413
+ 2. 整笔交易的 `nLockTime` 设为所有被花费稳定币 UTXO tape 中 `lockTime` 的最大值
414
+
415
+ 参考写法:
416
+
417
+ ```ts
418
+ import { Transaction } from "tbc-lib-js";
419
+ import { stableCoin } from "tbc-contract";
420
+
421
+ const tx = new Transaction().from(coinUtxos).from(payUtxo);
422
+ // ...addOutput(...)
423
+
424
+ for (let i = 0; i < coinUtxos.length; i++) {
425
+ tx.setInputSequence(i, 0xFFFFFFFE);
426
+ }
427
+
428
+ let lockTimeMax = 0;
429
+ for (let i = 0; i < coinUtxos.length; i++) {
430
+ const lt = stableCoin.getLockTimeFromTape(
431
+ preTXs[i].outputs[coinUtxos[i].outputIndex + 1].script
432
+ );
433
+ lockTimeMax = Math.max(lockTimeMax, lt);
434
+ }
435
+ tx.setLockTime(lockTimeMax);
436
+
437
+ const sourceTxraw = tx.uncheckedSerialize();
438
+ ```
439
+
440
+ > 对应的 `sourceUtxos` 条目仍要填 `"tbc20_coin"` 或 `"tbc20_coin_contract"`。
441
+
442
+ #### 稳定币示例
443
+
444
+ 父交易花掉 1 个稳定币 UTXO + 1 个 P2PKH UTXO,产生新的稳定币 UTXO(output 0/1 为 code/tape,output 2 为 P2PKH 找零);子交易再次花掉这个新稳定币 UTXO:
445
+
446
+ ```ts
447
+ const sourceUtxos: Input[] = [
448
+ {
449
+ txId: coinUtxo.txId,
450
+ outputIndex: coinUtxo.outputIndex,
451
+ satoshis: 500,
452
+ script: coinCodeHex,
453
+ scriptSigType: "tbc20_coin",
454
+ },
455
+ {
456
+ txId: payUtxo.txId,
457
+ outputIndex: payUtxo.outputIndex,
458
+ satoshis: 10000,
459
+ script: p2pkhHex,
460
+ scriptSigType: "p2pkh",
461
+ },
462
+ ];
463
+
464
+ const inputs: Input[][] = [
465
+ [
466
+ { outputIndex: 0, scriptSigType: "tbc20_coin" },
467
+ { outputIndex: 2, scriptSigType: "p2pkh" },
468
+ ],
469
+ ];
470
+
471
+ const outputs: Output[][] = [
472
+ [
473
+ { script: newCoinCodeHex, satoshis: 500 },
474
+ { script: newCoinTapeHex, satoshis: 0 },
475
+ { script: p2pkhChangeHex, satoshis: 8000 },
476
+ ],
477
+ ];
478
+
479
+ const { txraws } = await Turing.signAssociatedTransaction({
480
+ sourceTxraw,
481
+ sourceUtxos,
482
+ inputs,
483
+ outputs,
484
+ });
485
+ ```
486
+
487
+ 如果稳定币要走合约 / swap 路径,把 `scriptSigType` 改成 `"tbc20_coin_contract"`,并附上 `contractTxId` 与 `ftVersion`:
488
+
489
+ ```ts
490
+ {
491
+ outputIndex: 0,
492
+ scriptSigType: "tbc20_coin_contract",
493
+ contractTxId: "<合约交易 ID>",
494
+ ftVersion: 2,
495
+ }
266
496
  ```
267
497
 
268
498
  ## sendTransaction
@@ -17,6 +17,15 @@ export type Info = {
17
17
  version: string;
18
18
  };
19
19
 
20
+ export type GetNetworkResponse = {
21
+ network: "tbc" | "btc" | "eth" | "bnb" | "all";
22
+ type: "mainnet" | "testnet";
23
+ };
24
+
25
+ export type TuringNetworkChangedDetail = {
26
+ network: GetNetworkResponse;
27
+ };
28
+
20
29
  export type TransactionFlag =
21
30
  | "P2PKH"
22
31
  | "COLLECTION_CREATE"
@@ -125,7 +134,7 @@ export type Input = {
125
134
  script?: string;
126
135
  satoshis?: number;
127
136
  outputIndex: number;
128
- scriptSigType: "p2pkh" | "tbc20" | "tbc20_contract" | "other";
137
+ scriptSigType: "p2pkh" | "tbc20" | "tbc20_contract" | "tbc20_coin" | "tbc20_coin_contract" | "other";
129
138
  unfinishedScriptSig?: string;
130
139
  ftVersion?: 1 | 2;
131
140
  contractTxId?: string;
@@ -241,6 +250,7 @@ export type TuringProviderType = {
241
250
  getPubKey: () => Promise<PubKey | undefined>;
242
251
  getAddress: () => Promise<Address | undefined>;
243
252
  getInfo: () => Promise<Info | undefined>;
253
+ getNetwork: () => Promise<GetNetworkResponse | undefined>;
244
254
  sendTransaction: (
245
255
  params: SendTransaction[]
246
256
  ) => Promise<SendTransactionResponse | undefined>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "turing-wallet-provider",
3
- "version": "1.5.2",
3
+ "version": "1.5.4",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [