@ckb-ccc/xverse 1.0.32 → 1.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/CHANGELOG.md +29 -0
- package/dist/advanced.d.mts +2 -0
- package/dist/advanced.mjs +1 -0
- package/dist/advancedBarrel-C-ThB6-A.d.mts +481 -0
- package/dist/advancedBarrel-C-ThB6-A.d.mts.map +1 -0
- package/dist/advancedBarrel-DIYsVxWE.mjs +2 -0
- package/dist/advancedBarrel-DIYsVxWE.mjs.map +1 -0
- package/dist/advancedBarrel.d.mts +2 -0
- package/dist/advancedBarrel.mjs +1 -0
- package/dist/barrel.d.mts +101 -0
- package/dist/barrel.d.mts.map +1 -0
- package/dist/barrel.mjs +2 -0
- package/dist/barrel.mjs.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +1 -0
- package/dist/rolldown-runtime-DK3Fl9T5.mjs +1 -0
- package/dist.commonjs/advanced.d.ts +2 -2
- package/dist.commonjs/advanced.js +1 -37
- package/dist.commonjs/advancedBarrel-BCHIO_V8.d.ts +483 -0
- package/dist.commonjs/advancedBarrel-BCHIO_V8.d.ts.map +1 -0
- package/dist.commonjs/advancedBarrel-DA4O2d7u.js +2 -0
- package/dist.commonjs/advancedBarrel-DA4O2d7u.js.map +1 -0
- package/dist.commonjs/advancedBarrel.d.ts +2 -2
- package/dist.commonjs/advancedBarrel.js +1 -17
- package/dist.commonjs/barrel.d.ts +100 -2
- package/dist.commonjs/barrel.d.ts.map +1 -1
- package/dist.commonjs/barrel.js +2 -18
- package/dist.commonjs/barrel.js.map +1 -0
- package/dist.commonjs/index.d.ts +2 -2
- package/dist.commonjs/index.js +1 -37
- package/package.json +28 -30
- package/src/sat-connect-core/types.advanced.ts +6 -4
- package/src/signer.ts +159 -1
- package/tsdown.config.mts +43 -0
- package/dist/advanced.d.ts +0 -2
- package/dist/advanced.d.ts.map +0 -1
- package/dist/advanced.js +0 -1
- package/dist/advancedBarrel.d.ts +0 -2
- package/dist/advancedBarrel.d.ts.map +0 -1
- package/dist/advancedBarrel.js +0 -1
- package/dist/barrel.d.ts +0 -3
- package/dist/barrel.d.ts.map +0 -1
- package/dist/barrel.js +0 -2
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -1
- package/dist/sat-connect-core/advanced.d.ts +0 -5
- package/dist/sat-connect-core/advanced.d.ts.map +0 -1
- package/dist/sat-connect-core/advanced.js +0 -4
- package/dist/sat-connect-core/btcMethods.advanced.d.ts +0 -280
- package/dist/sat-connect-core/btcMethods.advanced.d.ts.map +0 -1
- package/dist/sat-connect-core/btcMethods.advanced.js +0 -179
- package/dist/sat-connect-core/provider.advanced.d.ts +0 -48
- package/dist/sat-connect-core/provider.advanced.d.ts.map +0 -1
- package/dist/sat-connect-core/provider.advanced.js +0 -21
- package/dist/sat-connect-core/requests.advanced.d.ts +0 -21
- package/dist/sat-connect-core/requests.advanced.d.ts.map +0 -1
- package/dist/sat-connect-core/requests.advanced.js +0 -1
- package/dist/sat-connect-core/types.advanced.d.ts +0 -124
- package/dist/sat-connect-core/types.advanced.d.ts.map +0 -1
- package/dist/sat-connect-core/types.advanced.js +0 -80
- package/dist/sat-connect-core/walletMethods.advanced.d.ts +0 -36
- package/dist/sat-connect-core/walletMethods.advanced.d.ts.map +0 -1
- package/dist/sat-connect-core/walletMethods.advanced.js +0 -37
- package/dist/signer.d.ts +0 -47
- package/dist/signer.d.ts.map +0 -1
- package/dist/signer.js +0 -125
- package/dist/signersFactory.d.ts +0 -13
- package/dist/signersFactory.d.ts.map +0 -1
- package/dist/signersFactory.js +0 -33
- package/dist.commonjs/advanced.d.ts.map +0 -1
- package/dist.commonjs/advancedBarrel.d.ts.map +0 -1
- package/dist.commonjs/index.d.ts.map +0 -1
- package/dist.commonjs/sat-connect-core/advanced.d.ts +0 -5
- package/dist.commonjs/sat-connect-core/advanced.d.ts.map +0 -1
- package/dist.commonjs/sat-connect-core/advanced.js +0 -20
- package/dist.commonjs/sat-connect-core/btcMethods.advanced.d.ts +0 -280
- package/dist.commonjs/sat-connect-core/btcMethods.advanced.d.ts.map +0 -1
- package/dist.commonjs/sat-connect-core/btcMethods.advanced.js +0 -215
- package/dist.commonjs/sat-connect-core/provider.advanced.d.ts +0 -48
- package/dist.commonjs/sat-connect-core/provider.advanced.d.ts.map +0 -1
- package/dist.commonjs/sat-connect-core/provider.advanced.js +0 -57
- package/dist.commonjs/sat-connect-core/requests.advanced.d.ts +0 -21
- package/dist.commonjs/sat-connect-core/requests.advanced.d.ts.map +0 -1
- package/dist.commonjs/sat-connect-core/requests.advanced.js +0 -2
- package/dist.commonjs/sat-connect-core/types.advanced.d.ts +0 -124
- package/dist.commonjs/sat-connect-core/types.advanced.d.ts.map +0 -1
- package/dist.commonjs/sat-connect-core/types.advanced.js +0 -116
- package/dist.commonjs/sat-connect-core/walletMethods.advanced.d.ts +0 -36
- package/dist.commonjs/sat-connect-core/walletMethods.advanced.d.ts.map +0 -1
- package/dist.commonjs/sat-connect-core/walletMethods.advanced.js +0 -73
- package/dist.commonjs/signer.d.ts +0 -47
- package/dist.commonjs/signer.d.ts.map +0 -1
- package/dist.commonjs/signer.js +0 -162
- package/dist.commonjs/signersFactory.d.ts +0 -13
- package/dist.commonjs/signersFactory.d.ts.map +0 -1
- package/dist.commonjs/signersFactory.js +0 -36
|
@@ -1,3 +1,101 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { Rt as __exportAll, bt as BtcProvider, n as Address } from "./advancedBarrel-BCHIO_V8.js";
|
|
2
|
+
import { ccc } from "@ckb-ccc/core";
|
|
3
|
+
|
|
4
|
+
//#region src/signer.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Class representing a Bitcoin signer that extends SignerBtc
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
declare class Signer extends ccc.SignerBtc {
|
|
10
|
+
readonly provider: BtcProvider;
|
|
11
|
+
private readonly preferredNetworks;
|
|
12
|
+
private addressCache;
|
|
13
|
+
/**
|
|
14
|
+
* Creates an instance of Signer.
|
|
15
|
+
* @param client - The client instance.
|
|
16
|
+
* @param provider - The provider instance.
|
|
17
|
+
*/
|
|
18
|
+
constructor(client: ccc.Client, provider: BtcProvider, preferredNetworks?: ccc.NetworkPreference[]);
|
|
19
|
+
assertAddress(): Promise<Address>;
|
|
20
|
+
/**
|
|
21
|
+
* Gets the Bitcoin account address.
|
|
22
|
+
* @returns A promise that resolves to the Bitcoin account address.
|
|
23
|
+
*/
|
|
24
|
+
getBtcAccount(): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Gets the Bitcoin public key.
|
|
27
|
+
* @returns A promise that resolves to the Bitcoin public key.
|
|
28
|
+
*/
|
|
29
|
+
getBtcPublicKey(): Promise<ccc.Hex>;
|
|
30
|
+
/**
|
|
31
|
+
* Connects to the provider by requesting accounts.
|
|
32
|
+
* @returns A promise that resolves when the connection is established.
|
|
33
|
+
*/
|
|
34
|
+
connect(): Promise<void>;
|
|
35
|
+
disconnect(): Promise<void>;
|
|
36
|
+
onReplaced(listener: () => void): () => void;
|
|
37
|
+
/**
|
|
38
|
+
* Checks if the signer is connected.
|
|
39
|
+
* @returns A promise that resolves to true if connected, false otherwise.
|
|
40
|
+
*/
|
|
41
|
+
isConnected(): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* Signs a raw message with the Bitcoin account.
|
|
44
|
+
* @param message - The message to sign.
|
|
45
|
+
* @returns A promise that resolves to the signed message.
|
|
46
|
+
*/
|
|
47
|
+
signMessageRaw(message: string | ccc.BytesLike): Promise<string>;
|
|
48
|
+
/**
|
|
49
|
+
* Build default inputsToSign for all unsigned inputs
|
|
50
|
+
*/
|
|
51
|
+
private buildDefaultinputsToSign;
|
|
52
|
+
private prepareSignPsbtParams;
|
|
53
|
+
/**
|
|
54
|
+
* Signs a PSBT using Xverse wallet.
|
|
55
|
+
*
|
|
56
|
+
* @param psbtHex - The hex string of PSBT to sign.
|
|
57
|
+
* @param options - Options for signing the PSBT
|
|
58
|
+
* @returns A promise that resolves to the signed PSBT as a Hex string
|
|
59
|
+
*
|
|
60
|
+
* @remarks
|
|
61
|
+
* Xverse accepts:
|
|
62
|
+
* - psbt: A string representing the PSBT to sign, encoded in base64
|
|
63
|
+
* - signInputs: A Record<string, number[]> where:
|
|
64
|
+
* - keys are the addresses to use for signing
|
|
65
|
+
* - values are the indexes of the inputs to sign with each address
|
|
66
|
+
*
|
|
67
|
+
* Xverse returns:
|
|
68
|
+
* - psbt: The base64 encoded signed PSBT
|
|
69
|
+
*
|
|
70
|
+
* @see https://docs.xverse.app/sats-connect/bitcoin-methods/signpsbt
|
|
71
|
+
*/
|
|
72
|
+
signPsbt(psbtHex: ccc.HexLike, options?: ccc.SignPsbtOptionsLike): Promise<ccc.Hex>;
|
|
73
|
+
/**
|
|
74
|
+
* Broadcasts a PSBT to the Bitcoin network.
|
|
75
|
+
*
|
|
76
|
+
* @remarks
|
|
77
|
+
* Xverse does not support broadcasting a signed PSBT directly.
|
|
78
|
+
* It only supports "Sign and Broadcast" as a single atomic operation via `signAndBroadcastPsbt`.
|
|
79
|
+
*/
|
|
80
|
+
broadcastPsbt(_psbtHex: ccc.HexLike, _options?: ccc.SignPsbtOptionsLike): Promise<ccc.Hex>;
|
|
81
|
+
signAndBroadcastPsbt(psbtHex: ccc.HexLike, options?: ccc.SignPsbtOptionsLike): Promise<ccc.Hex>;
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/signersFactory.d.ts
|
|
85
|
+
/**
|
|
86
|
+
* Retrieves the Xverse signer if available.
|
|
87
|
+
* @public
|
|
88
|
+
*
|
|
89
|
+
* @param client - The client instance.
|
|
90
|
+
* @returns All Xverse Signer instances
|
|
91
|
+
*/
|
|
92
|
+
declare function getXverseSigners(client: ccc.Client, preferredNetworks?: ccc.NetworkPreference[]): {
|
|
93
|
+
wallet: ccc.Wallet;
|
|
94
|
+
signerInfo: ccc.SignerInfo;
|
|
95
|
+
}[];
|
|
96
|
+
declare namespace barrel_d_exports {
|
|
97
|
+
export { Signer, getXverseSigners };
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { Signer, getXverseSigners, barrel_d_exports as t };
|
|
3
101
|
//# sourceMappingURL=barrel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"barrel.d.ts","
|
|
1
|
+
{"version":3,"file":"barrel.d.ts","names":[],"sources":["../src/signer.ts","../src/signersFactory.ts","../src/barrel.ts"],"mappings":";;;;;;AAyCA;;cAAa,MAAA,SAAe,GAAA,CAAI,SAAA;EAAA,SAUZ,QAAA,EAAU,WAAA;EAAA,iBACT,iBAAA;EAAA,QAVX,YAAA;EAU8B;;;;;cAFpC,MAAA,EAAQ,GAAA,CAAI,MAAA,EACI,QAAA,EAAU,WAAA,EACT,iBAAA,GAAmB,GAAA,CAAI,iBAAA;EAgBpC,aAAA,IAAiB,OAAA,CAAQ,OAAA;EAsDX;;;;EA1Bd,aAAA,IAAiB,OAAA;EA6KX;;;;EArKN,eAAA,IAAmB,OAAA,CAAQ,GAAA,CAAI,GAAA;EAmM1B;;;;EA3LL,OAAA,IAAW,OAAA;EAUX,UAAA,IAAc,OAAA;EAIpB,UAAA,CAAW,QAAA;EArF4B;;;;EAuGjC,WAAA,IAAe,OAAA;EA7FO;;;;;EA2GtB,cAAA,CAAe,OAAA,WAAkB,GAAA,CAAI,SAAA,GAAY,OAAA;EA5GrD;;;EAAA,QA8HM,wBAAA;EAAA,QAoCM,qBAAA;EAhKK;;;;;;;;;;;;;;;;;;;EAuNb,QAAA,CACJ,OAAA,EAAS,GAAA,CAAI,OAAA,EACb,OAAA,GAAU,GAAA,CAAI,mBAAA,GACb,OAAA,CAAQ,GAAA,CAAI,GAAA;EAhH4B;;;;;;;EA0IrC,aAAA,CACJ,QAAA,EAAU,GAAA,CAAI,OAAA,EACd,QAAA,GAAW,GAAA,CAAI,mBAAA,GACd,OAAA,CAAQ,GAAA,CAAI,GAAA;EAMT,oBAAA,CACJ,OAAA,EAAS,GAAA,CAAI,OAAA,EACb,OAAA,GAAU,GAAA,CAAI,mBAAA,GACb,OAAA,CAAQ,GAAA,CAAI,GAAA;AAAA;;;;;;AA3QjB;;;;iBCrBgB,gBAAA,CACd,MAAA,EAAQ,GAAA,CAAI,MAAA,EACZ,iBAAA,GAAoB,GAAA,CAAI,iBAAA;EACrB,MAAA,EAAQ,GAAA,CAAI,MAAA;EAAQ,UAAA,EAAY,GAAA,CAAI,UAAA;AAAA;AAAA"}
|
package/dist.commonjs/barrel.js
CHANGED
|
@@ -1,18 +1,2 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./signer.js"), exports);
|
|
18
|
-
__exportStar(require("./signersFactory.js"), exports);
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./advancedBarrel-DA4O2d7u.js");let t=require("@ckb-ccc/core"),n=require("bitcoinjs-lib"),r=require("valibot");r=e.V(r);async function i(t){let n=await t;if(r.is(e.I,n))throw n.error;if(r.is(e.z,n))return n.result;throw{code:-32603,message:`Received unknown response from provider.`,data:n}}var a=class extends t.ccc.SignerBtc{constructor(e,n,r=[{addressPrefix:`ckb`,signerType:t.ccc.SignerType.BTC,network:`btc`},{addressPrefix:`ckt`,signerType:t.ccc.SignerType.BTC,network:`btcTestnet`}]){super(e),this.provider=n,this.preferredNetworks=r}async assertAddress(){this.addressCache=this.addressCache??(async()=>{if(await this.isConnected())return(await i(this.provider.request(`getAddresses`,{purposes:[`payment`]}))).addresses[0]})();let e=await this.addressCache;if(e)return e;throw Error(`Not connected`)}async getBtcAccount(){return(await this.assertAddress()).address}async getBtcPublicKey(){return t.ccc.hexFrom((await this.assertAddress()).publicKey)}async connect(){await this.isConnected()||await i(this.provider.request(`wallet_requestPermissions`,void 0))}async disconnect(){this.addressCache=void 0}onReplaced(e){let t=[],n=()=>{e(),t[0]?.()};return t.push(this.provider.addListener(`accountChange`,n),this.provider.addListener(`networkChange`,n)),t[0]}async isConnected(){try{return await i(this.provider.request(`getBalance`,void 0)),!0}catch{return!1}}async signMessageRaw(e){let n=typeof e==`string`?e:t.ccc.hexFrom(e).slice(2);return(await i(this.provider.request(`signMessage`,{message:n,address:(await this.assertAddress()).address,protocol:`ECDSA`}))).signature}buildDefaultinputsToSign(e,t){let r=[];try{n.Psbt.fromHex(e.slice(2)).data.inputs.forEach((e,n)=>{e.finalScriptSig||e.finalScriptWitness||e.tapKeySig||e.partialSig&&e.partialSig.length>0||e.tapScriptSig&&e.tapScriptSig.length>0||r.push({index:n,address:t})})}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Failed to parse PSBT hex. Please provide inputsToSign explicitly in options. Original error: ${t}`,{cause:e})}return r}async prepareSignPsbtParams(e,n){let r=n?.inputsToSign;if(!r||!r.length){let t=await this.getBtcAccount();r=this.buildDefaultinputsToSign(e,t)}return{psbtBase64:t.ccc.bytesTo(e,`base64`),signInputs:r.reduce((e,t)=>{if(!t.address)throw Error(`Xverse only supports signing with address. Please provide 'address' in inputsToSign.`);return e[t.address]?e[t.address].push(t.index):e[t.address]=[t.index],e},{})}}async signPsbt(e,n){let{psbtBase64:r,signInputs:a}=await this.prepareSignPsbtParams(t.ccc.hexFrom(e),n),o=(await i(this.provider.request(`signPsbt`,{psbt:r,signInputs:a,broadcast:!1}))).psbt;return t.ccc.hexFrom(t.ccc.bytesFrom(o,`base64`))}async broadcastPsbt(e,t){throw Error(`Xverse does not support broadcasting signed PSBTs directly. Use signAndBroadcastPsbt instead.`)}async signAndBroadcastPsbt(e,n){let{psbtBase64:r,signInputs:a}=await this.prepareSignPsbtParams(t.ccc.hexFrom(e),n),o=await i(this.provider.request(`signPsbt`,{psbt:r,signInputs:a,broadcast:!0}));if(!o.txid)throw Error(`Failed to broadcast PSBT`);return t.ccc.hexFrom(o.txid)}};function o(e){return e?.split(`.`).reduce((e,t)=>e?.[t],window)}function s(e,t){let n=window;return n.btc_providers?n.btc_providers.map(n=>({wallet:{name:n.name,icon:n.icon},signerInfo:{name:`BTC`,signer:new a(e,o(n.id),t)}})):[]}var c=e.B({Signer:()=>a,getXverseSigners:()=>s});exports.Signer=a,exports.getXverseSigners=s,Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return c}});
|
|
2
|
+
//# sourceMappingURL=barrel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"barrel.js","names":["v","rpcErrorResponseMessageSchema","rpcSuccessResponseMessageSchema","ccc","Psbt"],"sources":["../src/signer.ts","../src/signersFactory.ts","../src/barrel.ts"],"sourcesContent":["import { ccc } from \"@ckb-ccc/core\";\nimport { Psbt } from \"bitcoinjs-lib\";\nimport * as v from \"valibot\";\nimport {\n Address,\n AddressPurpose,\n BtcProvider,\n MessageSigningProtocols,\n Requests,\n Return,\n RpcErrorCode,\n RpcResponse,\n rpcErrorResponseMessageSchema,\n rpcSuccessResponseMessageSchema,\n} from \"./advancedBarrel.js\";\n\nasync function checkResponse<T extends keyof Requests>(\n response: Promise<RpcResponse<T>>,\n): Promise<Return<T>> {\n const res = await response;\n if (v.is(rpcErrorResponseMessageSchema, res)) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw res.error;\n }\n\n if (v.is(rpcSuccessResponseMessageSchema, res)) {\n return res.result;\n }\n\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw {\n code: RpcErrorCode.INTERNAL_ERROR,\n message: \"Received unknown response from provider.\",\n data: res,\n };\n}\n\n/**\n * Class representing a Bitcoin signer that extends SignerBtc\n * @public\n */\nexport class Signer extends ccc.SignerBtc {\n private addressCache: Promise<Address | undefined> | undefined;\n\n /**\n * Creates an instance of Signer.\n * @param client - The client instance.\n * @param provider - The provider instance.\n */\n constructor(\n client: ccc.Client,\n public readonly provider: BtcProvider,\n private readonly preferredNetworks: ccc.NetworkPreference[] = [\n {\n addressPrefix: \"ckb\",\n signerType: ccc.SignerType.BTC,\n network: \"btc\",\n },\n {\n addressPrefix: \"ckt\",\n signerType: ccc.SignerType.BTC,\n network: \"btcTestnet\",\n },\n ],\n ) {\n super(client);\n }\n\n async assertAddress(): Promise<Address> {\n this.addressCache =\n this.addressCache ??\n (async () => {\n if (!(await this.isConnected())) {\n return;\n }\n\n return (\n await checkResponse(\n this.provider.request(\"getAddresses\", {\n purposes: [AddressPurpose.Payment],\n }),\n )\n ).addresses[0];\n })();\n const address = await this.addressCache;\n\n if (address) {\n return address;\n }\n throw Error(\"Not connected\");\n }\n\n /**\n * Gets the Bitcoin account address.\n * @returns A promise that resolves to the Bitcoin account address.\n */\n async getBtcAccount(): Promise<string> {\n return (await this.assertAddress()).address;\n }\n\n /**\n * Gets the Bitcoin public key.\n * @returns A promise that resolves to the Bitcoin public key.\n */\n async getBtcPublicKey(): Promise<ccc.Hex> {\n return ccc.hexFrom((await this.assertAddress()).publicKey);\n }\n\n /**\n * Connects to the provider by requesting accounts.\n * @returns A promise that resolves when the connection is established.\n */\n async connect(): Promise<void> {\n if (await this.isConnected()) {\n return;\n }\n\n await checkResponse(\n this.provider.request(\"wallet_requestPermissions\", undefined),\n );\n }\n\n async disconnect(): Promise<void> {\n this.addressCache = undefined;\n }\n\n onReplaced(listener: () => void): () => void {\n const stop: (() => void)[] = [];\n const replacer = () => {\n listener();\n stop[0]?.();\n };\n stop.push(\n this.provider.addListener(\"accountChange\", replacer),\n this.provider.addListener(\"networkChange\", replacer),\n );\n\n return stop[0];\n }\n\n /**\n * Checks if the signer is connected.\n * @returns A promise that resolves to true if connected, false otherwise.\n */\n async isConnected(): Promise<boolean> {\n try {\n await checkResponse(this.provider.request(\"getBalance\", undefined));\n return true;\n } catch (_error) {\n return false;\n }\n }\n\n /**\n * Signs a raw message with the Bitcoin account.\n * @param message - The message to sign.\n * @returns A promise that resolves to the signed message.\n */\n async signMessageRaw(message: string | ccc.BytesLike): Promise<string> {\n const challenge =\n typeof message === \"string\" ? message : ccc.hexFrom(message).slice(2);\n\n return (\n await checkResponse(\n this.provider.request(\"signMessage\", {\n message: challenge,\n address: (await this.assertAddress()).address,\n protocol: MessageSigningProtocols.ECDSA,\n }),\n )\n ).signature;\n }\n\n /**\n * Build default inputsToSign for all unsigned inputs\n */\n private buildDefaultinputsToSign(\n psbtHex: ccc.Hex,\n address: string,\n ): ccc.InputToSignLike[] {\n const inputsToSign: ccc.InputToSignLike[] = [];\n\n try {\n // Collect all unsigned inputs\n const psbt = Psbt.fromHex(psbtHex.slice(2));\n psbt.data.inputs.forEach((input, index) => {\n const isSigned =\n input.finalScriptSig ||\n input.finalScriptWitness ||\n input.tapKeySig ||\n (input.partialSig && input.partialSig.length > 0) ||\n (input.tapScriptSig && input.tapScriptSig.length > 0);\n\n if (!isSigned) {\n inputsToSign.push({ index, address });\n }\n });\n\n // If no unsigned inputs found, the PSBT is already fully signed\n // Let the wallet handle this case (likely a no-op or error)\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new Error(\n `Failed to parse PSBT hex. Please provide inputsToSign explicitly in options. Original error: ${errorMessage}`,\n { cause: error },\n );\n }\n\n return inputsToSign;\n }\n\n private async prepareSignPsbtParams(\n psbtHex: ccc.Hex,\n options?: ccc.SignPsbtOptionsLike,\n ): Promise<{\n psbtBase64: string;\n signInputs: Record<string, number[]>;\n }> {\n let inputsToSign = options?.inputsToSign;\n\n if (!inputsToSign || !inputsToSign.length) {\n const address = await this.getBtcAccount();\n inputsToSign = this.buildDefaultinputsToSign(psbtHex, address);\n }\n\n const psbtBase64 = ccc.bytesTo(psbtHex, \"base64\");\n\n const signInputs = inputsToSign.reduce(\n (acc, input) => {\n if (!input.address) {\n throw new Error(\n \"Xverse only supports signing with address. Please provide 'address' in inputsToSign.\",\n );\n }\n if (acc[input.address]) {\n acc[input.address].push(input.index);\n } else {\n acc[input.address] = [input.index];\n }\n return acc;\n },\n {} as Record<string, number[]>,\n );\n\n return { psbtBase64, signInputs };\n }\n\n /**\n * Signs a PSBT using Xverse wallet.\n *\n * @param psbtHex - The hex string of PSBT to sign.\n * @param options - Options for signing the PSBT\n * @returns A promise that resolves to the signed PSBT as a Hex string\n *\n * @remarks\n * Xverse accepts:\n * - psbt: A string representing the PSBT to sign, encoded in base64\n * - signInputs: A Record<string, number[]> where:\n * - keys are the addresses to use for signing\n * - values are the indexes of the inputs to sign with each address\n *\n * Xverse returns:\n * - psbt: The base64 encoded signed PSBT\n *\n * @see https://docs.xverse.app/sats-connect/bitcoin-methods/signpsbt\n */\n async signPsbt(\n psbtHex: ccc.HexLike,\n options?: ccc.SignPsbtOptionsLike,\n ): Promise<ccc.Hex> {\n const { psbtBase64, signInputs } = await this.prepareSignPsbtParams(\n ccc.hexFrom(psbtHex),\n options,\n );\n\n const signedPsbtBase64 = (\n await checkResponse(\n this.provider.request(\"signPsbt\", {\n psbt: psbtBase64,\n signInputs,\n broadcast: false,\n }),\n )\n ).psbt;\n\n return ccc.hexFrom(ccc.bytesFrom(signedPsbtBase64, \"base64\"));\n }\n\n /**\n * Broadcasts a PSBT to the Bitcoin network.\n *\n * @remarks\n * Xverse does not support broadcasting a signed PSBT directly.\n * It only supports \"Sign and Broadcast\" as a single atomic operation via `signAndBroadcastPsbt`.\n */\n async broadcastPsbt(\n _psbtHex: ccc.HexLike,\n _options?: ccc.SignPsbtOptionsLike,\n ): Promise<ccc.Hex> {\n throw new Error(\n \"Xverse does not support broadcasting signed PSBTs directly. Use signAndBroadcastPsbt instead.\",\n );\n }\n\n async signAndBroadcastPsbt(\n psbtHex: ccc.HexLike,\n options?: ccc.SignPsbtOptionsLike,\n ): Promise<ccc.Hex> {\n // ccc.hexFrom adds 0x prefix, but BTC expects non-0x\n const { psbtBase64, signInputs } = await this.prepareSignPsbtParams(\n ccc.hexFrom(psbtHex),\n options,\n );\n\n const result = await checkResponse(\n this.provider.request(\"signPsbt\", {\n psbt: psbtBase64,\n signInputs,\n broadcast: true,\n }),\n );\n\n if (!result.txid) {\n throw new Error(\"Failed to broadcast PSBT\");\n }\n\n return ccc.hexFrom(result.txid);\n }\n}\n","import { ccc } from \"@ckb-ccc/core\";\nimport { BtcProvider, Provider } from \"./advancedBarrel.js\";\nimport { Signer } from \"./signer.js\";\n\nfunction getProviderById(providerId: string) {\n return (\n providerId\n ?.split(\".\")\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return\n .reduce((acc: any, part) => acc?.[part], window) as BtcProvider\n );\n}\n\n/**\n * Retrieves the Xverse signer if available.\n * @public\n *\n * @param client - The client instance.\n * @returns All Xverse Signer instances\n */\nexport function getXverseSigners(\n client: ccc.Client,\n preferredNetworks?: ccc.NetworkPreference[],\n): { wallet: ccc.Wallet; signerInfo: ccc.SignerInfo }[] {\n const windowRef = window as {\n BitcoinProvider?: BtcProvider;\n XverseProviders?: {\n BitcoinProvider?: BtcProvider;\n };\n btc_providers?: Provider[];\n };\n\n const signers = (() => {\n if (windowRef.btc_providers) {\n return windowRef.btc_providers.map((provider) => ({\n wallet: {\n name: provider.name,\n icon: provider.icon,\n },\n signerInfo: {\n name: \"BTC\",\n signer: new Signer(\n client,\n getProviderById(provider.id),\n preferredNetworks,\n ),\n },\n }));\n }\n\n return [];\n })();\n\n return signers;\n}\n","export * from \"./signer.js\";\nexport * from \"./signersFactory.js\";\n"],"mappings":"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"}
|
package/dist.commonjs/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { t as barrel_d_exports } from "./barrel.js";
|
|
2
|
+
export { barrel_d_exports as Xverse };
|
package/dist.commonjs/index.js
CHANGED
|
@@ -1,37 +1 @@
|
|
|
1
|
-
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.Xverse = void 0;
|
|
37
|
-
exports.Xverse = __importStar(require("./barrel.js"));
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./barrel.js");Object.defineProperty(exports,"Xverse",{enumerable:!0,get:function(){return e.t}});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckb-ccc/xverse",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "CCC - CKBer's Codebase. Common Chains Connector's support for Xverse",
|
|
5
5
|
"author": "Hanssen0 <hanssen0@hanssen0.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,51 +11,49 @@
|
|
|
11
11
|
"url": "git://github.com/ckb-devrel/ccc.git"
|
|
12
12
|
},
|
|
13
13
|
"sideEffects": false,
|
|
14
|
-
"main": "dist.commonjs/index.js",
|
|
15
|
-
"module": "dist/index.
|
|
14
|
+
"main": "./dist.commonjs/index.js",
|
|
15
|
+
"module": "./dist/index.mjs",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
18
|
-
"import": "./dist/index.
|
|
19
|
-
"require": "./dist.commonjs/index.js"
|
|
20
|
-
"default": "./dist.commonjs/index.js"
|
|
21
|
-
},
|
|
22
|
-
"./barrel": {
|
|
23
|
-
"import": "./dist/barrel.js",
|
|
24
|
-
"require": "./dist.commonjs/barrel.js",
|
|
25
|
-
"default": "./dist.commonjs/barrel.js"
|
|
18
|
+
"import": "./dist/index.mjs",
|
|
19
|
+
"require": "./dist.commonjs/index.js"
|
|
26
20
|
},
|
|
27
21
|
"./advanced": {
|
|
28
|
-
"import": "./dist/advanced.
|
|
29
|
-
"require": "./dist.commonjs/advanced.js"
|
|
30
|
-
"default": "./dist.commonjs/advanced.js"
|
|
22
|
+
"import": "./dist/advanced.mjs",
|
|
23
|
+
"require": "./dist.commonjs/advanced.js"
|
|
31
24
|
},
|
|
32
25
|
"./advancedBarrel": {
|
|
33
|
-
"import": "./dist/advancedBarrel.
|
|
34
|
-
"require": "./dist.commonjs/advancedBarrel.js"
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
"import": "./dist/advancedBarrel.mjs",
|
|
27
|
+
"require": "./dist.commonjs/advancedBarrel.js"
|
|
28
|
+
},
|
|
29
|
+
"./barrel": {
|
|
30
|
+
"import": "./dist/barrel.mjs",
|
|
31
|
+
"require": "./dist.commonjs/barrel.js"
|
|
32
|
+
},
|
|
33
|
+
"./package.json": "./package.json"
|
|
37
34
|
},
|
|
38
35
|
"devDependencies": {
|
|
39
|
-
"@eslint/js": "^
|
|
40
|
-
"
|
|
41
|
-
"eslint": "^9.34.0",
|
|
36
|
+
"@eslint/js": "^10.0.1",
|
|
37
|
+
"eslint": "^10.5.0",
|
|
42
38
|
"eslint-config-prettier": "^10.1.8",
|
|
43
|
-
"eslint-plugin-prettier": "^5.5.
|
|
44
|
-
"prettier": "^3.
|
|
45
|
-
"prettier-plugin-organize-imports": "^4.
|
|
46
|
-
"
|
|
47
|
-
"typescript": "^
|
|
48
|
-
"typescript-eslint": "^8.41.0"
|
|
39
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
40
|
+
"prettier": "^3.8.4",
|
|
41
|
+
"prettier-plugin-organize-imports": "^4.3.0",
|
|
42
|
+
"typescript": "^6.0.3",
|
|
43
|
+
"typescript-eslint": "^8.61.1"
|
|
49
44
|
},
|
|
50
45
|
"publishConfig": {
|
|
51
46
|
"access": "public"
|
|
52
47
|
},
|
|
53
48
|
"dependencies": {
|
|
54
|
-
"
|
|
55
|
-
"
|
|
49
|
+
"bitcoinjs-lib": "^7.0.1",
|
|
50
|
+
"tsdown": "^0.22.3",
|
|
51
|
+
"valibot": "^1.4.1",
|
|
52
|
+
"@ckb-ccc/core": "1.14.0"
|
|
56
53
|
},
|
|
54
|
+
"types": "./dist.commonjs/index.d.ts",
|
|
57
55
|
"scripts": {
|
|
58
|
-
"build": "
|
|
56
|
+
"build": "tsdown",
|
|
59
57
|
"lint": "eslint ./src",
|
|
60
58
|
"format": "prettier --write . && eslint --fix ./src"
|
|
61
59
|
}
|
|
@@ -135,13 +135,15 @@ export interface RpcError {
|
|
|
135
135
|
data?: any;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
export interface RpcErrorResponse<
|
|
139
|
-
extends
|
|
138
|
+
export interface RpcErrorResponse<
|
|
139
|
+
TError extends RpcError = RpcError,
|
|
140
|
+
> extends RpcBase {
|
|
140
141
|
error: TError;
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
export interface RpcSuccessResponse<
|
|
144
|
-
extends
|
|
144
|
+
export interface RpcSuccessResponse<
|
|
145
|
+
Method extends keyof Requests,
|
|
146
|
+
> extends RpcBase {
|
|
145
147
|
result: Return<Method>;
|
|
146
148
|
}
|
|
147
149
|
|
package/src/signer.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ccc } from "@ckb-ccc/core";
|
|
2
|
+
import { Psbt } from "bitcoinjs-lib";
|
|
2
3
|
import * as v from "valibot";
|
|
3
4
|
import {
|
|
4
5
|
Address,
|
|
@@ -23,7 +24,7 @@ async function checkResponse<T extends keyof Requests>(
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
if (v.is(rpcSuccessResponseMessageSchema, res)) {
|
|
26
|
-
return res.result
|
|
27
|
+
return res.result;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
// eslint-disable-next-line @typescript-eslint/only-throw-error
|
|
@@ -169,4 +170,161 @@ export class Signer extends ccc.SignerBtc {
|
|
|
169
170
|
)
|
|
170
171
|
).signature;
|
|
171
172
|
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Build default inputsToSign for all unsigned inputs
|
|
176
|
+
*/
|
|
177
|
+
private buildDefaultinputsToSign(
|
|
178
|
+
psbtHex: ccc.Hex,
|
|
179
|
+
address: string,
|
|
180
|
+
): ccc.InputToSignLike[] {
|
|
181
|
+
const inputsToSign: ccc.InputToSignLike[] = [];
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
// Collect all unsigned inputs
|
|
185
|
+
const psbt = Psbt.fromHex(psbtHex.slice(2));
|
|
186
|
+
psbt.data.inputs.forEach((input, index) => {
|
|
187
|
+
const isSigned =
|
|
188
|
+
input.finalScriptSig ||
|
|
189
|
+
input.finalScriptWitness ||
|
|
190
|
+
input.tapKeySig ||
|
|
191
|
+
(input.partialSig && input.partialSig.length > 0) ||
|
|
192
|
+
(input.tapScriptSig && input.tapScriptSig.length > 0);
|
|
193
|
+
|
|
194
|
+
if (!isSigned) {
|
|
195
|
+
inputsToSign.push({ index, address });
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// If no unsigned inputs found, the PSBT is already fully signed
|
|
200
|
+
// Let the wallet handle this case (likely a no-op or error)
|
|
201
|
+
} catch (error) {
|
|
202
|
+
const errorMessage =
|
|
203
|
+
error instanceof Error ? error.message : String(error);
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Failed to parse PSBT hex. Please provide inputsToSign explicitly in options. Original error: ${errorMessage}`,
|
|
206
|
+
{ cause: error },
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return inputsToSign;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private async prepareSignPsbtParams(
|
|
214
|
+
psbtHex: ccc.Hex,
|
|
215
|
+
options?: ccc.SignPsbtOptionsLike,
|
|
216
|
+
): Promise<{
|
|
217
|
+
psbtBase64: string;
|
|
218
|
+
signInputs: Record<string, number[]>;
|
|
219
|
+
}> {
|
|
220
|
+
let inputsToSign = options?.inputsToSign;
|
|
221
|
+
|
|
222
|
+
if (!inputsToSign || !inputsToSign.length) {
|
|
223
|
+
const address = await this.getBtcAccount();
|
|
224
|
+
inputsToSign = this.buildDefaultinputsToSign(psbtHex, address);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const psbtBase64 = ccc.bytesTo(psbtHex, "base64");
|
|
228
|
+
|
|
229
|
+
const signInputs = inputsToSign.reduce(
|
|
230
|
+
(acc, input) => {
|
|
231
|
+
if (!input.address) {
|
|
232
|
+
throw new Error(
|
|
233
|
+
"Xverse only supports signing with address. Please provide 'address' in inputsToSign.",
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
if (acc[input.address]) {
|
|
237
|
+
acc[input.address].push(input.index);
|
|
238
|
+
} else {
|
|
239
|
+
acc[input.address] = [input.index];
|
|
240
|
+
}
|
|
241
|
+
return acc;
|
|
242
|
+
},
|
|
243
|
+
{} as Record<string, number[]>,
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
return { psbtBase64, signInputs };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Signs a PSBT using Xverse wallet.
|
|
251
|
+
*
|
|
252
|
+
* @param psbtHex - The hex string of PSBT to sign.
|
|
253
|
+
* @param options - Options for signing the PSBT
|
|
254
|
+
* @returns A promise that resolves to the signed PSBT as a Hex string
|
|
255
|
+
*
|
|
256
|
+
* @remarks
|
|
257
|
+
* Xverse accepts:
|
|
258
|
+
* - psbt: A string representing the PSBT to sign, encoded in base64
|
|
259
|
+
* - signInputs: A Record<string, number[]> where:
|
|
260
|
+
* - keys are the addresses to use for signing
|
|
261
|
+
* - values are the indexes of the inputs to sign with each address
|
|
262
|
+
*
|
|
263
|
+
* Xverse returns:
|
|
264
|
+
* - psbt: The base64 encoded signed PSBT
|
|
265
|
+
*
|
|
266
|
+
* @see https://docs.xverse.app/sats-connect/bitcoin-methods/signpsbt
|
|
267
|
+
*/
|
|
268
|
+
async signPsbt(
|
|
269
|
+
psbtHex: ccc.HexLike,
|
|
270
|
+
options?: ccc.SignPsbtOptionsLike,
|
|
271
|
+
): Promise<ccc.Hex> {
|
|
272
|
+
const { psbtBase64, signInputs } = await this.prepareSignPsbtParams(
|
|
273
|
+
ccc.hexFrom(psbtHex),
|
|
274
|
+
options,
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
const signedPsbtBase64 = (
|
|
278
|
+
await checkResponse(
|
|
279
|
+
this.provider.request("signPsbt", {
|
|
280
|
+
psbt: psbtBase64,
|
|
281
|
+
signInputs,
|
|
282
|
+
broadcast: false,
|
|
283
|
+
}),
|
|
284
|
+
)
|
|
285
|
+
).psbt;
|
|
286
|
+
|
|
287
|
+
return ccc.hexFrom(ccc.bytesFrom(signedPsbtBase64, "base64"));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Broadcasts a PSBT to the Bitcoin network.
|
|
292
|
+
*
|
|
293
|
+
* @remarks
|
|
294
|
+
* Xverse does not support broadcasting a signed PSBT directly.
|
|
295
|
+
* It only supports "Sign and Broadcast" as a single atomic operation via `signAndBroadcastPsbt`.
|
|
296
|
+
*/
|
|
297
|
+
async broadcastPsbt(
|
|
298
|
+
_psbtHex: ccc.HexLike,
|
|
299
|
+
_options?: ccc.SignPsbtOptionsLike,
|
|
300
|
+
): Promise<ccc.Hex> {
|
|
301
|
+
throw new Error(
|
|
302
|
+
"Xverse does not support broadcasting signed PSBTs directly. Use signAndBroadcastPsbt instead.",
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
async signAndBroadcastPsbt(
|
|
307
|
+
psbtHex: ccc.HexLike,
|
|
308
|
+
options?: ccc.SignPsbtOptionsLike,
|
|
309
|
+
): Promise<ccc.Hex> {
|
|
310
|
+
// ccc.hexFrom adds 0x prefix, but BTC expects non-0x
|
|
311
|
+
const { psbtBase64, signInputs } = await this.prepareSignPsbtParams(
|
|
312
|
+
ccc.hexFrom(psbtHex),
|
|
313
|
+
options,
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
const result = await checkResponse(
|
|
317
|
+
this.provider.request("signPsbt", {
|
|
318
|
+
psbt: psbtBase64,
|
|
319
|
+
signInputs,
|
|
320
|
+
broadcast: true,
|
|
321
|
+
}),
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
if (!result.txid) {
|
|
325
|
+
throw new Error("Failed to broadcast PSBT");
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return ccc.hexFrom(result.txid);
|
|
329
|
+
}
|
|
172
330
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { defineConfig } from "tsdown";
|
|
2
|
+
|
|
3
|
+
const common = {
|
|
4
|
+
minify: true,
|
|
5
|
+
dts: true,
|
|
6
|
+
platform: "neutral" as const,
|
|
7
|
+
sourcemap: true,
|
|
8
|
+
exports: true,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const entry = {
|
|
12
|
+
index: "src/index.ts",
|
|
13
|
+
barrel: "src/barrel.ts",
|
|
14
|
+
advanced: "src/advanced.ts",
|
|
15
|
+
advancedBarrel: "src/advancedBarrel.ts",
|
|
16
|
+
} as const;
|
|
17
|
+
|
|
18
|
+
const bundleDeps: string[] = [];
|
|
19
|
+
|
|
20
|
+
export default defineConfig(
|
|
21
|
+
(
|
|
22
|
+
[
|
|
23
|
+
{
|
|
24
|
+
entry,
|
|
25
|
+
deps: {
|
|
26
|
+
onlyBundle: [] as string[],
|
|
27
|
+
},
|
|
28
|
+
format: "esm",
|
|
29
|
+
copy: "./misc/basedirs/dist/*",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
entry,
|
|
33
|
+
deps: {
|
|
34
|
+
alwaysBundle: bundleDeps,
|
|
35
|
+
onlyBundle: bundleDeps,
|
|
36
|
+
},
|
|
37
|
+
format: "cjs",
|
|
38
|
+
outDir: "dist.commonjs",
|
|
39
|
+
copy: "./misc/basedirs/dist.commonjs/*",
|
|
40
|
+
},
|
|
41
|
+
] as const
|
|
42
|
+
).map((c) => ({ ...c, ...common })),
|
|
43
|
+
);
|
package/dist/advanced.d.ts
DELETED
package/dist/advanced.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"advanced.d.ts","sourceRoot":"","sources":["../src/advanced.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC"}
|
package/dist/advanced.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * as XverseA from "./advancedBarrel.js";
|
package/dist/advancedBarrel.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"advancedBarrel.d.ts","sourceRoot":"","sources":["../src/advancedBarrel.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC"}
|
package/dist/advancedBarrel.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./sat-connect-core/advanced.js";
|
package/dist/barrel.d.ts
DELETED
package/dist/barrel.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"barrel.d.ts","sourceRoot":"","sources":["../src/barrel.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC"}
|
package/dist/barrel.js
DELETED
package/dist/index.d.ts
DELETED
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC"}
|
package/dist/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * as Xverse from "./barrel.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"advanced.d.ts","sourceRoot":"","sources":["../../src/sat-connect-core/advanced.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC"}
|