@lombard.finance/sdk-common 3.1.0 → 3.4.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/README.md +0 -0
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +37 -13
- package/dist/index.js.map +1 -0
- package/package.json +16 -9
- package/src/env.ts +1 -0
- package/src/index.ts +5 -0
- package/src/modules.ts +108 -0
- package/src/providers.ts +53 -0
- package/src/services/api.ts +140 -0
- package/src/services/btc.ts +24 -0
- package/src/services/evm.ts +105 -0
- package/src/services/index.ts +22 -0
- package/src/services/solana.ts +31 -0
- package/src/services/starknet.ts +31 -0
- package/src/services/sui.ts +33 -0
- package/src/utils/bitcoin.ts +30 -0
- package/src/utils/btc-address-type.ts +22 -0
- package/src/utils/err.ts +85 -0
- package/src/utils/get-output-script.ts +6 -10
- package/src/utils/numbers.ts +17 -0
- package/src/vite-env.d.ts +0 -0
package/README.md
CHANGED
|
File without changes
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty
|
|
1
|
+
"use strict";var u=Object.create;var s=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var l=Object.getPrototypeOf,b=Object.prototype.hasOwnProperty;var S=(t,i,e,c)=>{if(i&&typeof i=="object"||typeof i=="function")for(let n of d(i))!b.call(t,n)&&n!==e&&s(t,n,{get:()=>i[n],enumerable:!(c=p(i,n))||c.enumerable});return t};var a=(t,i,e)=>(e=t!=null?u(l(t)):{},S(i||!t||!t.__esModule?s(e,"default",{value:t,enumerable:!0}):e,t));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o={prod:"prod",testnet:"testnet",stage:"stage",dev:"dev",ibc:"ibc"},g=o.prod,y=["evm","bitcoin","solana","sui","starknet"];let r=null;const E=async()=>{try{const t=await import("bitcoinjs-lib"),i=await import("@bitcoinerlab/secp256k1");try{t.initEccLib(i)}catch(e){if(!/already initialized/i.test(String(e)))throw e}return t}catch(t){throw r=null,new Error(`Failed to initialize bitcoinjs-lib: ${t instanceof Error?t.message:String(t)}. Ensure bitcoinjs-lib and @bitcoinerlab/secp256k1 peer dependencies are installed.`)}},v=async()=>(r||(r=E()),r);async function w(t,i=o.prod){const e=await v();return`0x${e.address.toOutputScript(t,i===o.prod?e.networks.bitcoin:e.networks.testnet).toString("hex")}`}exports.DEFAULT_ENV=g;exports.Env=o;exports.ProviderKeys=y;exports.getOutputScript=w;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/env.ts","../src/providers.ts","../src/utils/bitcoin.ts","../src/utils/get-output-script.ts"],"sourcesContent":["export const Env = {\n prod: 'prod',\n testnet: 'testnet',\n stage: 'stage',\n dev: 'dev',\n ibc: 'ibc',\n} as const;\n\nexport type Env = (typeof Env)[keyof typeof Env];\n\nexport const DEFAULT_ENV: Env = Env.prod;\n","import type { EIP1193Provider } from 'viem';\n\n/**\n * Provider interfaces shared between the core SDK and optional chain modules.\n */\nexport interface EvmProvider extends EIP1193Provider {}\n\nexport interface BtcProvider {\n getAddresses(): Promise<string[]>;\n signMessage(message: string): Promise<string>;\n getNetwork?(): Promise<string>;\n}\n\nexport interface SolanaProvider {\n signMessage(message: Uint8Array | string): Promise<{ signature: Uint8Array }>;\n publicKey?: { toString(): string };\n network?: string;\n}\n\nexport interface SuiProvider {\n getWallet(): unknown;\n getWalletAccount(): unknown;\n}\n\nexport interface StarknetProvider {\n getProvider(): unknown;\n}\n\nexport type AnyProvider =\n | EvmProvider\n | BtcProvider\n | SolanaProvider\n | SuiProvider\n | StarknetProvider;\n\nexport const ProviderKeys = [\n 'evm',\n 'bitcoin',\n 'solana',\n 'sui',\n 'starknet',\n] as const;\nexport type ProviderKey = (typeof ProviderKeys)[number];\n\nexport interface ProviderMap {\n evm: EvmProvider;\n bitcoin: BtcProvider;\n solana: SolanaProvider;\n sui: SuiProvider;\n starknet: StarknetProvider;\n}\n\nexport type ProviderFor<TKey extends ProviderKey> = ProviderMap[TKey];\n","let bitcoinPromise: Promise<typeof import('bitcoinjs-lib')> | null = null;\n\nconst initBitcoin = async (): Promise<typeof import('bitcoinjs-lib')> => {\n try {\n const module = await import('bitcoinjs-lib');\n const ecc = await import('@bitcoinerlab/secp256k1');\n try {\n module.initEccLib(ecc);\n } catch (err) {\n if (!/already initialized/i.test(String(err))) {\n throw err;\n }\n }\n return module;\n } catch (err) {\n // Reset promise so subsequent calls can retry\n bitcoinPromise = null;\n throw new Error(\n `Failed to initialize bitcoinjs-lib: ${err instanceof Error ? err.message : String(err)}. ` +\n 'Ensure bitcoinjs-lib and @bitcoinerlab/secp256k1 peer dependencies are installed.',\n );\n }\n};\n\nexport const getBitcoin = async (): Promise<typeof import('bitcoinjs-lib')> => {\n if (!bitcoinPromise) {\n bitcoinPromise = initBitcoin();\n }\n return bitcoinPromise;\n};\n","import { Env } from '../env';\nimport { getBitcoin } from './bitcoin';\n\n/**\n * Get output script from address.\n *\n * @param address - The address.\n * @param env\n *\n * @returns The output script.\n */\nexport async function getOutputScript(\n address: string,\n env: Env = Env.prod,\n): Promise<`0x${string}`> {\n const bitcoin = await getBitcoin();\n const outputScriptBuf = bitcoin.address.toOutputScript(\n address,\n env === Env.prod ? bitcoin.networks.bitcoin : bitcoin.networks.testnet,\n );\n const outputScript = outputScriptBuf.toString('hex');\n return `0x${outputScript}`;\n}\n"],"names":["Env","DEFAULT_ENV","ProviderKeys","bitcoinPromise","initBitcoin","module","ecc","err","getBitcoin","getOutputScript","address","env","bitcoin"],"mappings":"2hBAAO,MAAMA,EAAM,CACjB,KAAM,OACN,QAAS,UACT,MAAO,QACP,IAAK,MACL,IAAK,KACP,EAIaC,EAAmBD,EAAI,KCyBvBE,EAAe,CAC1B,MACA,UACA,SACA,MACA,UACF,ECzCA,IAAIC,EAAiE,KAErE,MAAMC,EAAc,SAAqD,CACvE,GAAI,CACF,MAAMC,EAAS,KAAM,QAAO,eAAe,EACrCC,EAAM,KAAM,QAAO,yBAAyB,EAClD,GAAI,CACFD,EAAO,WAAWC,CAAG,CACvB,OAASC,EAAK,CACZ,GAAI,CAAC,uBAAuB,KAAK,OAAOA,CAAG,CAAC,EAC1C,MAAMA,CAEV,CACA,OAAOF,CACT,OAASE,EAAK,CAEZ,MAAAJ,EAAiB,KACX,IAAI,MACR,uCAAuCI,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,CAAC,qFAAA,CAG3F,CACF,EAEaC,EAAa,UACnBL,IACHA,EAAiBC,EAAA,GAEZD,GCjBT,eAAsBM,EACpBC,EACAC,EAAWX,EAAI,KACS,CACxB,MAAMY,EAAU,MAAMJ,EAAA,EAMtB,MAAO,KALiBI,EAAQ,QAAQ,eACtCF,EACAC,IAAQX,EAAI,KAAOY,EAAQ,SAAS,QAAUA,EAAQ,SAAS,OAAA,EAE5B,SAAS,KAAK,CAC3B,EAC1B"}
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
import { initEccLib as i, address as u, networks as r } from "bitcoinjs-lib";
|
|
3
|
-
const t = {
|
|
1
|
+
const r = {
|
|
4
2
|
prod: "prod",
|
|
5
3
|
testnet: "testnet",
|
|
6
4
|
stage: "stage",
|
|
7
|
-
dev: "dev"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
dev: "dev",
|
|
6
|
+
ibc: "ibc"
|
|
7
|
+
}, p = r.prod, u = [
|
|
8
|
+
"evm",
|
|
9
|
+
"bitcoin",
|
|
10
|
+
"solana",
|
|
11
|
+
"sui",
|
|
12
|
+
"starknet"
|
|
13
|
+
];
|
|
14
|
+
let n = null;
|
|
15
|
+
const o = async () => {
|
|
16
|
+
try {
|
|
17
|
+
const t = await import("bitcoinjs-lib"), e = await import("@bitcoinerlab/secp256k1");
|
|
18
|
+
try {
|
|
19
|
+
t.initEccLib(e);
|
|
20
|
+
} catch (i) {
|
|
21
|
+
if (!/already initialized/i.test(String(i)))
|
|
22
|
+
throw i;
|
|
23
|
+
}
|
|
24
|
+
return t;
|
|
25
|
+
} catch (t) {
|
|
26
|
+
throw n = null, new Error(
|
|
27
|
+
`Failed to initialize bitcoinjs-lib: ${t instanceof Error ? t.message : String(t)}. Ensure bitcoinjs-lib and @bitcoinerlab/secp256k1 peer dependencies are installed.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}, c = async () => (n || (n = o()), n);
|
|
31
|
+
async function d(t, e = r.prod) {
|
|
32
|
+
const i = await c();
|
|
33
|
+
return `0x${i.address.toOutputScript(
|
|
34
|
+
t,
|
|
35
|
+
e === r.prod ? i.networks.bitcoin : i.networks.testnet
|
|
14
36
|
).toString("hex")}`;
|
|
15
37
|
}
|
|
16
38
|
export {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
39
|
+
p as DEFAULT_ENV,
|
|
40
|
+
r as Env,
|
|
41
|
+
u as ProviderKeys,
|
|
42
|
+
d as getOutputScript
|
|
20
43
|
};
|
|
44
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/env.ts","../src/providers.ts","../src/utils/bitcoin.ts","../src/utils/get-output-script.ts"],"sourcesContent":["export const Env = {\n prod: 'prod',\n testnet: 'testnet',\n stage: 'stage',\n dev: 'dev',\n ibc: 'ibc',\n} as const;\n\nexport type Env = (typeof Env)[keyof typeof Env];\n\nexport const DEFAULT_ENV: Env = Env.prod;\n","import type { EIP1193Provider } from 'viem';\n\n/**\n * Provider interfaces shared between the core SDK and optional chain modules.\n */\nexport interface EvmProvider extends EIP1193Provider {}\n\nexport interface BtcProvider {\n getAddresses(): Promise<string[]>;\n signMessage(message: string): Promise<string>;\n getNetwork?(): Promise<string>;\n}\n\nexport interface SolanaProvider {\n signMessage(message: Uint8Array | string): Promise<{ signature: Uint8Array }>;\n publicKey?: { toString(): string };\n network?: string;\n}\n\nexport interface SuiProvider {\n getWallet(): unknown;\n getWalletAccount(): unknown;\n}\n\nexport interface StarknetProvider {\n getProvider(): unknown;\n}\n\nexport type AnyProvider =\n | EvmProvider\n | BtcProvider\n | SolanaProvider\n | SuiProvider\n | StarknetProvider;\n\nexport const ProviderKeys = [\n 'evm',\n 'bitcoin',\n 'solana',\n 'sui',\n 'starknet',\n] as const;\nexport type ProviderKey = (typeof ProviderKeys)[number];\n\nexport interface ProviderMap {\n evm: EvmProvider;\n bitcoin: BtcProvider;\n solana: SolanaProvider;\n sui: SuiProvider;\n starknet: StarknetProvider;\n}\n\nexport type ProviderFor<TKey extends ProviderKey> = ProviderMap[TKey];\n","let bitcoinPromise: Promise<typeof import('bitcoinjs-lib')> | null = null;\n\nconst initBitcoin = async (): Promise<typeof import('bitcoinjs-lib')> => {\n try {\n const module = await import('bitcoinjs-lib');\n const ecc = await import('@bitcoinerlab/secp256k1');\n try {\n module.initEccLib(ecc);\n } catch (err) {\n if (!/already initialized/i.test(String(err))) {\n throw err;\n }\n }\n return module;\n } catch (err) {\n // Reset promise so subsequent calls can retry\n bitcoinPromise = null;\n throw new Error(\n `Failed to initialize bitcoinjs-lib: ${err instanceof Error ? err.message : String(err)}. ` +\n 'Ensure bitcoinjs-lib and @bitcoinerlab/secp256k1 peer dependencies are installed.',\n );\n }\n};\n\nexport const getBitcoin = async (): Promise<typeof import('bitcoinjs-lib')> => {\n if (!bitcoinPromise) {\n bitcoinPromise = initBitcoin();\n }\n return bitcoinPromise;\n};\n","import { Env } from '../env';\nimport { getBitcoin } from './bitcoin';\n\n/**\n * Get output script from address.\n *\n * @param address - The address.\n * @param env\n *\n * @returns The output script.\n */\nexport async function getOutputScript(\n address: string,\n env: Env = Env.prod,\n): Promise<`0x${string}`> {\n const bitcoin = await getBitcoin();\n const outputScriptBuf = bitcoin.address.toOutputScript(\n address,\n env === Env.prod ? bitcoin.networks.bitcoin : bitcoin.networks.testnet,\n );\n const outputScript = outputScriptBuf.toString('hex');\n return `0x${outputScript}`;\n}\n"],"names":["Env","DEFAULT_ENV","ProviderKeys","bitcoinPromise","initBitcoin","module","ecc","err","getBitcoin","getOutputScript","address","env","bitcoin"],"mappings":"AAAO,MAAMA,IAAM;AAAA,EACjB,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,KAAK;AAAA,EACL,KAAK;AACP,GAIaC,IAAmBD,EAAI,MCyBvBE,IAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;ACzCA,IAAIC,IAAiE;AAErE,MAAMC,IAAc,YAAqD;AACvE,MAAI;AACF,UAAMC,IAAS,MAAM,OAAO,eAAe,GACrCC,IAAM,MAAM,OAAO,yBAAyB;AAClD,QAAI;AACF,MAAAD,EAAO,WAAWC,CAAG;AAAA,IACvB,SAASC,GAAK;AACZ,UAAI,CAAC,uBAAuB,KAAK,OAAOA,CAAG,CAAC;AAC1C,cAAMA;AAAA,IAEV;AACA,WAAOF;AAAA,EACT,SAASE,GAAK;AAEZ,UAAAJ,IAAiB,MACX,IAAI;AAAA,MACR,uCAAuCI,aAAe,QAAQA,EAAI,UAAU,OAAOA,CAAG,CAAC;AAAA,IAAA;AAAA,EAG3F;AACF,GAEaC,IAAa,aACnBL,MACHA,IAAiBC,EAAA,IAEZD;ACjBT,eAAsBM,EACpBC,GACAC,IAAWX,EAAI,MACS;AACxB,QAAMY,IAAU,MAAMJ,EAAA;AAMtB,SAAO,KALiBI,EAAQ,QAAQ;AAAA,IACtCF;AAAA,IACAC,MAAQX,EAAI,OAAOY,EAAQ,SAAS,UAAUA,EAAQ,SAAS;AAAA,EAAA,EAE5B,SAAS,KAAK,CAC3B;AAC1B;"}
|
package/package.json
CHANGED
|
@@ -1,35 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lombard.finance/sdk-common",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": {
|
|
6
6
|
"types": "./src/index.ts",
|
|
7
7
|
"import": "./dist/index.js",
|
|
8
8
|
"require": "./dist/index.cjs"
|
|
9
|
-
}
|
|
9
|
+
},
|
|
10
|
+
"./utils/*": "./src/utils/*.ts"
|
|
10
11
|
},
|
|
11
12
|
"license": "MIT",
|
|
12
13
|
"type": "module",
|
|
13
14
|
"types": "./src/index.ts",
|
|
14
|
-
"files": [
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src"
|
|
18
|
+
],
|
|
15
19
|
"engines": {
|
|
16
|
-
"node": ">=
|
|
20
|
+
"node": ">= 18.0.0"
|
|
17
21
|
},
|
|
18
22
|
"scripts": {
|
|
19
23
|
"build-docs": "rimraf ./sdk-docs && typedoc --out sdk-docs",
|
|
20
24
|
"build": "yarn types && vite build",
|
|
21
|
-
"lint": "
|
|
25
|
+
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --max-warnings=0",
|
|
26
|
+
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
|
|
27
|
+
"format:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\"",
|
|
22
28
|
"types": "tsc --noEmit"
|
|
23
29
|
},
|
|
24
30
|
"peerDependencies": {
|
|
25
|
-
"@
|
|
26
|
-
"bitcoinjs-lib": "6.1.5"
|
|
31
|
+
"@bitcoinerlab/secp256k1": "^1.2.0",
|
|
32
|
+
"bitcoinjs-lib": "^6.1.5"
|
|
27
33
|
},
|
|
28
34
|
"devDependencies": {
|
|
29
|
-
"@
|
|
35
|
+
"@bitcoinerlab/secp256k1": "1.2.0",
|
|
36
|
+
"bitcoinjs-lib": "6.1.5",
|
|
30
37
|
"rimraf": "^5",
|
|
31
38
|
"typedoc": "^0.26.6",
|
|
32
39
|
"typescript": "^5.4.5",
|
|
33
|
-
"
|
|
40
|
+
"vite": "^6.3.5"
|
|
34
41
|
}
|
|
35
42
|
}
|
package/src/env.ts
CHANGED
package/src/index.ts
CHANGED
package/src/modules.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Env } from './env';
|
|
2
|
+
import type { ProviderFor, ProviderKey } from './providers';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shared token for cross-module state
|
|
6
|
+
*/
|
|
7
|
+
export type SharedToken<T> = symbol & { __sharedToken?: T };
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Context provided to modules during registration
|
|
11
|
+
*/
|
|
12
|
+
export interface RegisterContext {
|
|
13
|
+
env: Env;
|
|
14
|
+
getProvider<TKey extends ProviderKey>(key: TKey): Promise<ProviderFor<TKey>>;
|
|
15
|
+
getShared<T>(token: SharedToken<T>): T | undefined;
|
|
16
|
+
setShared<T>(token: SharedToken<T>, value: T): void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* SDK Module - Generic module interface
|
|
21
|
+
*
|
|
22
|
+
* Base interface for all SDK modules. Modules are thin factories that
|
|
23
|
+
* instantiate services and register them with the SDK.
|
|
24
|
+
*
|
|
25
|
+
* Use this for non-chain-specific modules (e.g., apiModule).
|
|
26
|
+
*
|
|
27
|
+
* @template TId - Unique module identifier
|
|
28
|
+
* @template TService - Service interface the module provides
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* function apiModule(): SdkModule<'api', ApiService> {
|
|
33
|
+
* return {
|
|
34
|
+
* id: 'api',
|
|
35
|
+
* register(ctx) {
|
|
36
|
+
* return new ApiService(ctx.env);
|
|
37
|
+
* },
|
|
38
|
+
* };
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export interface SdkModule<TId extends string = string, TService = unknown> {
|
|
43
|
+
/** Unique module identifier */
|
|
44
|
+
id: TId;
|
|
45
|
+
/** Provider keys required by this module */
|
|
46
|
+
requiresProviders?: ProviderKey[];
|
|
47
|
+
/** Factory function that creates the service */
|
|
48
|
+
register(ctx: RegisterContext): TService;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Chain Module - Module interface for blockchain-specific services
|
|
53
|
+
*
|
|
54
|
+
* Extension of SdkModule for chain-specific modules. Adds a `chain` field
|
|
55
|
+
* to identify the blockchain type.
|
|
56
|
+
*
|
|
57
|
+
* Use this for chain-specific modules (e.g., btcModule, evmModule, solanaModule).
|
|
58
|
+
*
|
|
59
|
+
* @template TChain - Chain type identifier (e.g., 'btc', 'evm', 'solana')
|
|
60
|
+
* @template TService - Service interface the module provides
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* function evmModule(): ChainModule<'evm', EvmService> {
|
|
65
|
+
* return {
|
|
66
|
+
* id: 'evm',
|
|
67
|
+
* chain: 'evm',
|
|
68
|
+
* register(ctx) {
|
|
69
|
+
* return new EvmService(ctx.env);
|
|
70
|
+
* },
|
|
71
|
+
* };
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export interface ChainModule<TChain extends string = string, TService = unknown>
|
|
76
|
+
extends SdkModule<TChain, TService> {
|
|
77
|
+
/** Chain type this module provides services for */
|
|
78
|
+
chain: TChain;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Any module type (either SdkModule or ChainModule)
|
|
83
|
+
*/
|
|
84
|
+
export type AnyModule =
|
|
85
|
+
| SdkModule<string, unknown>
|
|
86
|
+
| ChainModule<string, unknown>;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Extract module ID type from a module
|
|
90
|
+
*/
|
|
91
|
+
export type ModuleId<TModule> =
|
|
92
|
+
TModule extends SdkModule<infer TId, unknown> ? TId : never;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Extract service type from a module by ID
|
|
96
|
+
*/
|
|
97
|
+
export type ServiceOf<TModule extends SdkModule<string, unknown>, TId extends string> =
|
|
98
|
+
TModule extends SdkModule<TId, infer TService> ? TService : never;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @deprecated Use ServiceOf instead
|
|
102
|
+
*/
|
|
103
|
+
export type CapabilitiesOf<
|
|
104
|
+
TModule extends ChainModule<string, unknown>,
|
|
105
|
+
TId extends string,
|
|
106
|
+
> = TModule extends ChainModule<string, infer TCapabilities> & { id: TId }
|
|
107
|
+
? TCapabilities
|
|
108
|
+
: never;
|
package/src/providers.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { EIP1193Provider } from 'viem';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Provider interfaces shared between the core SDK and optional chain modules.
|
|
5
|
+
*/
|
|
6
|
+
export interface EvmProvider extends EIP1193Provider {}
|
|
7
|
+
|
|
8
|
+
export interface BtcProvider {
|
|
9
|
+
getAddresses(): Promise<string[]>;
|
|
10
|
+
signMessage(message: string): Promise<string>;
|
|
11
|
+
getNetwork?(): Promise<string>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SolanaProvider {
|
|
15
|
+
signMessage(message: Uint8Array | string): Promise<{ signature: Uint8Array }>;
|
|
16
|
+
publicKey?: { toString(): string };
|
|
17
|
+
network?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SuiProvider {
|
|
21
|
+
getWallet(): unknown;
|
|
22
|
+
getWalletAccount(): unknown;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface StarknetProvider {
|
|
26
|
+
getProvider(): unknown;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type AnyProvider =
|
|
30
|
+
| EvmProvider
|
|
31
|
+
| BtcProvider
|
|
32
|
+
| SolanaProvider
|
|
33
|
+
| SuiProvider
|
|
34
|
+
| StarknetProvider;
|
|
35
|
+
|
|
36
|
+
export const ProviderKeys = [
|
|
37
|
+
'evm',
|
|
38
|
+
'bitcoin',
|
|
39
|
+
'solana',
|
|
40
|
+
'sui',
|
|
41
|
+
'starknet',
|
|
42
|
+
] as const;
|
|
43
|
+
export type ProviderKey = (typeof ProviderKeys)[number];
|
|
44
|
+
|
|
45
|
+
export interface ProviderMap {
|
|
46
|
+
evm: EvmProvider;
|
|
47
|
+
bitcoin: BtcProvider;
|
|
48
|
+
solana: SolanaProvider;
|
|
49
|
+
sui: SuiProvider;
|
|
50
|
+
starknet: StarknetProvider;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type ProviderFor<TKey extends ProviderKey> = ProviderMap[TKey];
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Service
|
|
3
|
+
*
|
|
4
|
+
* Operations for Lombard backend API provided by apiModule() or built-in.
|
|
5
|
+
* Used by actions for deposit address generation and tracking.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Destination chain ID (EVM numeric, Solana string, etc.)
|
|
10
|
+
*/
|
|
11
|
+
export type DestinationChainId = number | string;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Deposit information returned from API
|
|
15
|
+
*/
|
|
16
|
+
export interface DepositInfo {
|
|
17
|
+
depositAddress: string;
|
|
18
|
+
blockHeight?: number;
|
|
19
|
+
isClaimed: boolean;
|
|
20
|
+
txid?: string;
|
|
21
|
+
amount?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Parameters for generating a deposit address
|
|
26
|
+
*/
|
|
27
|
+
export interface GenerateDepositAddressParams {
|
|
28
|
+
/** Recipient address on destination chain */
|
|
29
|
+
address: string;
|
|
30
|
+
/** Destination chain ID */
|
|
31
|
+
chainId: DestinationChainId;
|
|
32
|
+
/** Authorization signature */
|
|
33
|
+
signature: string;
|
|
34
|
+
/**
|
|
35
|
+
* Token to mint (LBTC, BTCb, etc.)
|
|
36
|
+
* REQUIRED - determines which token contract address is used
|
|
37
|
+
*/
|
|
38
|
+
token: string;
|
|
39
|
+
/** EIP-712 typed data (for EVM) */
|
|
40
|
+
eip712Data?: string;
|
|
41
|
+
/** Signature data (for stake and bake) */
|
|
42
|
+
signatureData?: string;
|
|
43
|
+
/** Public key (for non-EVM chains) */
|
|
44
|
+
pubKey?: string;
|
|
45
|
+
/** Partner ID for attribution */
|
|
46
|
+
partnerId?: string;
|
|
47
|
+
/** Referral code */
|
|
48
|
+
referrerCode?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Parameters for getting an existing deposit address
|
|
53
|
+
*/
|
|
54
|
+
export interface GetDepositAddressParams {
|
|
55
|
+
address: string;
|
|
56
|
+
chainId: DestinationChainId;
|
|
57
|
+
/** Token to look up (LBTC, BTCb, etc.) - REQUIRED */
|
|
58
|
+
token: string;
|
|
59
|
+
partnerId?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Fee signature storage parameters
|
|
64
|
+
*/
|
|
65
|
+
export interface StoreFeeSignatureParams {
|
|
66
|
+
address: string;
|
|
67
|
+
signature: string;
|
|
68
|
+
typedData: string;
|
|
69
|
+
/** Token address to distinguish LBTC vs BTC.b signatures */
|
|
70
|
+
tokenAddress?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Fee signature retrieval parameters
|
|
75
|
+
*/
|
|
76
|
+
export interface GetFeeSignatureParams {
|
|
77
|
+
address: string;
|
|
78
|
+
chainId: number;
|
|
79
|
+
/** Token address to distinguish LBTC vs BTC.b signatures */
|
|
80
|
+
tokenAddress?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Fee signature result
|
|
85
|
+
*/
|
|
86
|
+
export interface FeeSignatureResult {
|
|
87
|
+
hasSignature: boolean;
|
|
88
|
+
signature?: string;
|
|
89
|
+
typedData?: string;
|
|
90
|
+
expirationDate?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Stake and bake signature storage parameters
|
|
95
|
+
*/
|
|
96
|
+
export interface StoreStakeAndBakeParams {
|
|
97
|
+
signature: string;
|
|
98
|
+
typedData: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* API Service Interface
|
|
103
|
+
*
|
|
104
|
+
* Provides all Lombard backend API operations.
|
|
105
|
+
* Injected into contexts as `ctx.api`.
|
|
106
|
+
*/
|
|
107
|
+
export interface ApiService {
|
|
108
|
+
/**
|
|
109
|
+
* Generate a new BTC deposit address
|
|
110
|
+
*/
|
|
111
|
+
generateDepositAddress(params: GenerateDepositAddressParams): Promise<string>;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get existing deposit address for a recipient
|
|
115
|
+
* Returns undefined if no address exists
|
|
116
|
+
*/
|
|
117
|
+
getDepositAddress(
|
|
118
|
+
params: GetDepositAddressParams,
|
|
119
|
+
): Promise<string | undefined>;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get deposits for an address
|
|
123
|
+
*/
|
|
124
|
+
getDeposits(address: string): Promise<DepositInfo[]>;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Store network fee signature
|
|
128
|
+
*/
|
|
129
|
+
storeFeeSignature(params: StoreFeeSignatureParams): Promise<void>;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Get stored network fee signature
|
|
133
|
+
*/
|
|
134
|
+
getFeeSignature(params: GetFeeSignatureParams): Promise<FeeSignatureResult>;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Store stake and bake signature
|
|
138
|
+
*/
|
|
139
|
+
storeStakeAndBakeSignature(params: StoreStakeAndBakeParams): Promise<void>;
|
|
140
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BTC Chain Service
|
|
3
|
+
*
|
|
4
|
+
* Operations for Bitcoin blockchain provided by btcModule().
|
|
5
|
+
* Used by strategies for BTC deposit monitoring and address operations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Network mode for Bitcoin operations
|
|
10
|
+
*/
|
|
11
|
+
export type BtcNetworkMode = 'mainnet' | 'testnet';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* BTC Service Interface
|
|
15
|
+
*
|
|
16
|
+
* Provides Bitcoin-specific operations.
|
|
17
|
+
* Injected into BtcCoreContext as `ctx.btc`.
|
|
18
|
+
*/
|
|
19
|
+
export interface BtcService {
|
|
20
|
+
/**
|
|
21
|
+
* Get current block height from mempool
|
|
22
|
+
*/
|
|
23
|
+
getCurrentBlockHeight(network: BtcNetworkMode): Promise<number>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EVM Chain Service
|
|
3
|
+
*
|
|
4
|
+
* Operations for EVM-compatible blockchains provided by evmModule().
|
|
5
|
+
* Used by strategies for contract interactions and fee authorization.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { EvmProvider } from '../providers';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Chain ID type (numeric EVM chain identifier)
|
|
12
|
+
*/
|
|
13
|
+
export type EvmChainId = number;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Fee authorization result
|
|
17
|
+
*/
|
|
18
|
+
export interface FeeAuthorizationResult {
|
|
19
|
+
signature: string;
|
|
20
|
+
typedData?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Stored fee signature result (from resume flow)
|
|
25
|
+
*/
|
|
26
|
+
export interface StoredFeeSignature {
|
|
27
|
+
hasSignature: boolean;
|
|
28
|
+
signature?: string;
|
|
29
|
+
typedData?: string;
|
|
30
|
+
expirationDate?: string;
|
|
31
|
+
isDelayed?: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Network fee signing parameters
|
|
36
|
+
*/
|
|
37
|
+
export interface SignNetworkFeeParams {
|
|
38
|
+
fee: string;
|
|
39
|
+
account: string;
|
|
40
|
+
chainId: EvmChainId;
|
|
41
|
+
provider: EvmProvider;
|
|
42
|
+
/** Token to sign for (LBTC or BTCb). Defaults to LBTC for backwards compatibility. */
|
|
43
|
+
token?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Network fee signing result
|
|
48
|
+
*/
|
|
49
|
+
export interface SignNetworkFeeResult {
|
|
50
|
+
signature: string;
|
|
51
|
+
typedData: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Stake and bake signing parameters
|
|
56
|
+
*/
|
|
57
|
+
export interface SignStakeAndBakeParams {
|
|
58
|
+
value: string;
|
|
59
|
+
account: string;
|
|
60
|
+
chainId: EvmChainId;
|
|
61
|
+
provider: EvmProvider;
|
|
62
|
+
vaultKey: string;
|
|
63
|
+
token: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* EVM Service Interface
|
|
68
|
+
*
|
|
69
|
+
* Provides all EVM-specific operations.
|
|
70
|
+
* Injected into contexts as `ctx.evm`.
|
|
71
|
+
*/
|
|
72
|
+
export interface EvmService {
|
|
73
|
+
/**
|
|
74
|
+
* Get minting fee for a chain
|
|
75
|
+
* @param chainId - The chain ID
|
|
76
|
+
* @param token - Optional token (defaults to LBTC). Use 'BTCb' for BTC.b deposits.
|
|
77
|
+
*/
|
|
78
|
+
getMintingFee(chainId: EvmChainId, token?: string): Promise<string>;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Sign network fee authorization (EIP-712)
|
|
82
|
+
*/
|
|
83
|
+
signNetworkFee(params: SignNetworkFeeParams): Promise<SignNetworkFeeResult>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get stake and bake fee for a vault
|
|
87
|
+
*/
|
|
88
|
+
getStakeAndBakeFee(chainId: EvmChainId, vaultKey: string): Promise<string>;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Sign stake and bake authorization
|
|
92
|
+
*/
|
|
93
|
+
signStakeAndBake(
|
|
94
|
+
params: SignStakeAndBakeParams,
|
|
95
|
+
): Promise<SignNetworkFeeResult>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Sign LBTC destination address (for non-Ethereum EVM chains)
|
|
99
|
+
*/
|
|
100
|
+
signLbtcDestination(params: {
|
|
101
|
+
chainId: EvmChainId;
|
|
102
|
+
address: string;
|
|
103
|
+
provider: EvmProvider;
|
|
104
|
+
}): Promise<{ signature: string }>;
|
|
105
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chain Services
|
|
3
|
+
*
|
|
4
|
+
* Interfaces for what modules provide to actions.
|
|
5
|
+
* Each chain module (btcModule, evmModule, solanaModule, etc.)
|
|
6
|
+
* returns a service implementing one of these interfaces.
|
|
7
|
+
*
|
|
8
|
+
* Service-First Pattern:
|
|
9
|
+
* - Service interfaces define the contract
|
|
10
|
+
* - Service implementation classes contain the logic
|
|
11
|
+
* - Modules are thin factories that instantiate services
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Core services (provided by sdk)
|
|
15
|
+
export * from './api';
|
|
16
|
+
export * from './btc';
|
|
17
|
+
export * from './evm';
|
|
18
|
+
|
|
19
|
+
// External chain services (provided by sdk-solana, sdk-sui, etc.)
|
|
20
|
+
export * from './solana';
|
|
21
|
+
export * from './starknet';
|
|
22
|
+
export * from './sui';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solana Chain Service
|
|
3
|
+
*
|
|
4
|
+
* Operations for Solana blockchain provided by solanaModule().
|
|
5
|
+
* Used by strategies that mint/send to Solana.
|
|
6
|
+
*/
|
|
7
|
+
export interface SolanaService {
|
|
8
|
+
/**
|
|
9
|
+
* Sign LBTC destination address for Solana minting
|
|
10
|
+
* Required to generate a BTC deposit address for Solana destination
|
|
11
|
+
*/
|
|
12
|
+
signLbtcDestination(args: {
|
|
13
|
+
network: string;
|
|
14
|
+
}): Promise<{ signature: string }>;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Unstake LBTC on Solana to receive BTC
|
|
18
|
+
*
|
|
19
|
+
* Burns LBTC on Solana and releases BTC to the provided Bitcoin address.
|
|
20
|
+
*
|
|
21
|
+
* @param args.amount - Amount of LBTC to unstake in base units (satoshis)
|
|
22
|
+
* @param args.btcAddress - Bitcoin address to receive BTC
|
|
23
|
+
* @param args.network - Solana network ('mainnet-beta', 'devnet', 'testnet')
|
|
24
|
+
* @returns Transaction signature
|
|
25
|
+
*/
|
|
26
|
+
unstake(args: {
|
|
27
|
+
amount: string;
|
|
28
|
+
btcAddress: string;
|
|
29
|
+
network: string;
|
|
30
|
+
}): Promise<{ txHash: string }>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Starknet Chain Service
|
|
3
|
+
*
|
|
4
|
+
* Operations for Starknet blockchain provided by starknetModule().
|
|
5
|
+
* Used by strategies that mint/send to Starknet.
|
|
6
|
+
*/
|
|
7
|
+
export interface StarknetService {
|
|
8
|
+
/**
|
|
9
|
+
* Sign LBTC destination address for Starknet minting
|
|
10
|
+
* Required to generate a BTC deposit address for Starknet destination
|
|
11
|
+
*/
|
|
12
|
+
signLbtcDestination(args: {
|
|
13
|
+
chainId: string;
|
|
14
|
+
}): Promise<{ signature: string; pubKey: string }>;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Unstake LBTC on Starknet to receive BTC
|
|
18
|
+
*
|
|
19
|
+
* Burns LBTC on Starknet and releases BTC to the provided Bitcoin address.
|
|
20
|
+
*
|
|
21
|
+
* @param args.amount - Amount of LBTC to unstake (BTC decimal, e.g., "0.001")
|
|
22
|
+
* @param args.btcAddress - Bitcoin address to receive BTC
|
|
23
|
+
* @param args.env - Environment (prod, testnet, stage, dev)
|
|
24
|
+
* @returns Transaction hash
|
|
25
|
+
*/
|
|
26
|
+
unstake(args: {
|
|
27
|
+
amount: string;
|
|
28
|
+
btcAddress: string;
|
|
29
|
+
env: string;
|
|
30
|
+
}): Promise<{ txHash: string }>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sui Chain Service
|
|
3
|
+
*
|
|
4
|
+
* Operations for Sui blockchain provided by suiModule().
|
|
5
|
+
* Used by strategies that mint/send to Sui.
|
|
6
|
+
*/
|
|
7
|
+
export interface SuiService {
|
|
8
|
+
/**
|
|
9
|
+
* Sign LBTC destination address for Sui minting
|
|
10
|
+
* Required to generate a BTC deposit address for Sui destination
|
|
11
|
+
*/
|
|
12
|
+
signLbtcDestination(args: {
|
|
13
|
+
chainId: string;
|
|
14
|
+
}): Promise<{ signature: string }>;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Unstake LBTC on Sui to receive BTC
|
|
18
|
+
*
|
|
19
|
+
* Burns LBTC on Sui and releases BTC to the provided Bitcoin address.
|
|
20
|
+
*
|
|
21
|
+
* @param args.amount - Amount of LBTC to unstake (BTC decimal, e.g., "0.001")
|
|
22
|
+
* @param args.btcAddress - Bitcoin address to receive BTC
|
|
23
|
+
* @param args.chainId - Sui chain ID ('sui:mainnet', 'sui:testnet')
|
|
24
|
+
* @param args.env - Environment (prod, testnet, stage, dev)
|
|
25
|
+
* @returns Transaction digest (hash)
|
|
26
|
+
*/
|
|
27
|
+
unstake(args: {
|
|
28
|
+
amount: string;
|
|
29
|
+
btcAddress: string;
|
|
30
|
+
chainId: string;
|
|
31
|
+
env: string;
|
|
32
|
+
}): Promise<{ txHash: string }>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
let bitcoinPromise: Promise<typeof import('bitcoinjs-lib')> | null = null;
|
|
2
|
+
|
|
3
|
+
const initBitcoin = async (): Promise<typeof import('bitcoinjs-lib')> => {
|
|
4
|
+
try {
|
|
5
|
+
const module = await import('bitcoinjs-lib');
|
|
6
|
+
const ecc = await import('@bitcoinerlab/secp256k1');
|
|
7
|
+
try {
|
|
8
|
+
module.initEccLib(ecc);
|
|
9
|
+
} catch (err) {
|
|
10
|
+
if (!/already initialized/i.test(String(err))) {
|
|
11
|
+
throw err;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return module;
|
|
15
|
+
} catch (err) {
|
|
16
|
+
// Reset promise so subsequent calls can retry
|
|
17
|
+
bitcoinPromise = null;
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Failed to initialize bitcoinjs-lib: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
20
|
+
'Ensure bitcoinjs-lib and @bitcoinerlab/secp256k1 peer dependencies are installed.',
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const getBitcoin = async (): Promise<typeof import('bitcoinjs-lib')> => {
|
|
26
|
+
if (!bitcoinPromise) {
|
|
27
|
+
bitcoinPromise = initBitcoin();
|
|
28
|
+
}
|
|
29
|
+
return bitcoinPromise;
|
|
30
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { address } from 'bitcoinjs-lib';
|
|
2
|
+
|
|
3
|
+
export enum BtcAddressType {
|
|
4
|
+
p2tr = 'p2tr',
|
|
5
|
+
p2wpkh = 'p2wpkh',
|
|
6
|
+
p2wsh = 'p2wsh',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getBtcAddressType(btcAddress: string): BtcAddressType {
|
|
10
|
+
const { data, version } = address.fromBech32(btcAddress);
|
|
11
|
+
|
|
12
|
+
if (version === 0) {
|
|
13
|
+
if (data.length === 20) return BtcAddressType.p2wpkh;
|
|
14
|
+
if (data.length === 32) return BtcAddressType.p2wsh;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (version === 1) {
|
|
18
|
+
if (data.length === 32) return BtcAddressType.p2tr;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
throw new Error('Invalid BTC address');
|
|
22
|
+
}
|
package/src/utils/err.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { AxiosError } from 'axios';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Extract a readable error message from any error object
|
|
5
|
+
* @param error Error object to extract message from
|
|
6
|
+
* @returns A readable error message string
|
|
7
|
+
*/
|
|
8
|
+
export function extractErrorMessage(error: unknown): string {
|
|
9
|
+
// If error is already a string, return it
|
|
10
|
+
if (typeof error === 'string') {
|
|
11
|
+
return error;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Check for data.message pattern (common in API error responses)
|
|
15
|
+
const hasDataMessage = (
|
|
16
|
+
err: unknown,
|
|
17
|
+
): err is { data: { message: string } } => {
|
|
18
|
+
if (err === null || typeof err !== 'object') return false;
|
|
19
|
+
if (!('data' in err) || err.data === null || typeof err.data !== 'object')
|
|
20
|
+
return false;
|
|
21
|
+
if (!('message' in err.data)) return false;
|
|
22
|
+
return typeof err.data.message === 'string';
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
if (hasDataMessage(error)) {
|
|
26
|
+
return error.data.message;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Handle standard Error objects and Axios errors
|
|
30
|
+
if (error instanceof Error) {
|
|
31
|
+
if ('isAxiosError' in error && error.isAxiosError) {
|
|
32
|
+
return extractAxiosErrorMessage(error as unknown as AxiosError);
|
|
33
|
+
}
|
|
34
|
+
return error.message;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Handle generic objects with a message property
|
|
38
|
+
if (error !== null && typeof error === 'object') {
|
|
39
|
+
if ('message' in error && typeof error.message === 'string') {
|
|
40
|
+
return error.message;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Try to convert object to a readable string
|
|
44
|
+
try {
|
|
45
|
+
return JSON.stringify(error);
|
|
46
|
+
} catch {
|
|
47
|
+
// If JSON.stringify fails, return a generic message
|
|
48
|
+
return 'Unknown error object';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return 'Unknown error';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Extract error message from an Axios error
|
|
57
|
+
* @param error Axios error object
|
|
58
|
+
* @returns Error message from the Axios error
|
|
59
|
+
*/
|
|
60
|
+
function extractAxiosErrorMessage(error: AxiosError): string {
|
|
61
|
+
if (error.response) {
|
|
62
|
+
const responseData = error.response.data;
|
|
63
|
+
if (responseData && typeof responseData === 'object') {
|
|
64
|
+
if (
|
|
65
|
+
'message' in responseData &&
|
|
66
|
+
responseData.message &&
|
|
67
|
+
typeof responseData.message === 'string'
|
|
68
|
+
) {
|
|
69
|
+
return responseData.message;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
return JSON.stringify(responseData);
|
|
73
|
+
} catch {
|
|
74
|
+
return 'Error in API response';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return `HTTP error ${error.response.status}: ${error.response.statusText}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (error.message) {
|
|
81
|
+
return error.message;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return 'Network error';
|
|
85
|
+
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import * as ecc from '@bitcoin-js/tiny-secp256k1-asmjs';
|
|
2
|
-
import { address as addressUtils, initEccLib, networks } from 'bitcoinjs-lib';
|
|
3
1
|
import { Env } from '../env';
|
|
4
|
-
|
|
5
|
-
initEccLib(ecc);
|
|
2
|
+
import { getBitcoin } from './bitcoin';
|
|
6
3
|
|
|
7
4
|
/**
|
|
8
5
|
* Get output script from address.
|
|
@@ -12,15 +9,14 @@ initEccLib(ecc);
|
|
|
12
9
|
*
|
|
13
10
|
* @returns The output script.
|
|
14
11
|
*/
|
|
15
|
-
export function getOutputScript(
|
|
12
|
+
export async function getOutputScript(
|
|
16
13
|
address: string,
|
|
17
14
|
env: Env = Env.prod,
|
|
18
|
-
):
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const outputScriptBuf = addressUtils.toOutputScript(
|
|
15
|
+
): Promise<`0x${string}`> {
|
|
16
|
+
const bitcoin = await getBitcoin();
|
|
17
|
+
const outputScriptBuf = bitcoin.address.toOutputScript(
|
|
22
18
|
address,
|
|
23
|
-
env === Env.prod ? networks.bitcoin : networks.testnet,
|
|
19
|
+
env === Env.prod ? bitcoin.networks.bitcoin : bitcoin.networks.testnet,
|
|
24
20
|
);
|
|
25
21
|
const outputScript = outputScriptBuf.toString('hex');
|
|
26
22
|
return `0x${outputScript}`;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import BigNumber from 'bignumber.js';
|
|
2
|
+
|
|
3
|
+
export function toBaseDenomination(
|
|
4
|
+
input: BigNumber.Value,
|
|
5
|
+
decimalPlaces: number,
|
|
6
|
+
) {
|
|
7
|
+
return BigNumber(input)
|
|
8
|
+
.multipliedBy(BigNumber(10).pow(decimalPlaces))
|
|
9
|
+
.decimalPlaces(0, BigNumber.ROUND_HALF_UP);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function fromBaseDenomination(
|
|
13
|
+
input: BigNumber.Value,
|
|
14
|
+
decimalPlaces: number,
|
|
15
|
+
) {
|
|
16
|
+
return BigNumber(input).dividedBy(BigNumber(10).pow(decimalPlaces));
|
|
17
|
+
}
|
package/src/vite-env.d.ts
CHANGED
|
File without changes
|