gate-evm-tools 1.0.22 → 1.0.23
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 +47 -0
- package/dist/custody/credential.d.ts +16 -0
- package/dist/custody/credential.d.ts.map +1 -0
- package/dist/custody/credential.js +68 -0
- package/dist/custody/credential.js.map +1 -0
- package/dist/custody/hardhat-runtime.d.ts +16 -0
- package/dist/custody/hardhat-runtime.d.ts.map +1 -0
- package/dist/custody/hardhat-runtime.js +101 -0
- package/dist/custody/hardhat-runtime.js.map +1 -0
- package/dist/custody/hardhat.d.ts +3 -0
- package/dist/custody/hardhat.d.ts.map +1 -0
- package/dist/custody/hardhat.js +8 -0
- package/dist/custody/hardhat.js.map +1 -0
- package/dist/custody/index.d.ts +6 -0
- package/dist/custody/index.d.ts.map +1 -0
- package/dist/custody/index.js +6 -0
- package/dist/custody/index.js.map +1 -0
- package/dist/custody/service.d.ts +16 -0
- package/dist/custody/service.d.ts.map +1 -0
- package/dist/custody/service.js +100 -0
- package/dist/custody/service.js.map +1 -0
- package/dist/custody/signer.d.ts +13 -0
- package/dist/custody/signer.d.ts.map +1 -0
- package/dist/custody/signer.js +258 -0
- package/dist/custody/signer.js.map +1 -0
- package/dist/custody/version.d.ts +4 -0
- package/dist/custody/version.d.ts.map +1 -0
- package/dist/custody/version.js +13 -0
- package/dist/custody/version.js.map +1 -0
- package/dist-cjs/custody/credential.js +74 -0
- package/dist-cjs/custody/credential.js.map +1 -0
- package/dist-cjs/custody/hardhat-runtime.js +104 -0
- package/dist-cjs/custody/hardhat-runtime.js.map +1 -0
- package/dist-cjs/custody/hardhat.js +15 -0
- package/dist-cjs/custody/hardhat.js.map +1 -0
- package/dist-cjs/custody/index.js +18 -0
- package/dist-cjs/custody/index.js.map +1 -0
- package/dist-cjs/custody/service.js +105 -0
- package/dist-cjs/custody/service.js.map +1 -0
- package/dist-cjs/custody/signer.js +261 -0
- package/dist-cjs/custody/signer.js.map +1 -0
- package/dist-cjs/custody/version.js +16 -0
- package/dist-cjs/custody/version.js.map +1 -0
- package/dist-cjs/package.json +3 -0
- package/package.json +32 -4
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { parseWalletCredential } from './credential.js';
|
|
2
|
+
import { CustodyServiceClient, requireResponseString, } from './service.js';
|
|
3
|
+
import { detectEthersMajor } from './version.js';
|
|
4
|
+
export function createSigner(options) {
|
|
5
|
+
const credential = parseWalletCredential(options.credential);
|
|
6
|
+
const major = detectEthersMajor(options.ethers);
|
|
7
|
+
if (credential.kind === 'private-key') {
|
|
8
|
+
const Wallet = requireRuntimeConstructor(options.ethers, 'Wallet');
|
|
9
|
+
return new Wallet(credential.privateKey, options.provider ?? null);
|
|
10
|
+
}
|
|
11
|
+
if (options.provider === undefined || options.provider === null) {
|
|
12
|
+
throw new Error('托管钱包凭证必须同时提供 ethers Provider');
|
|
13
|
+
}
|
|
14
|
+
const address = normalizeAddress(options.ethers, major, credential.address);
|
|
15
|
+
const clientOptions = {
|
|
16
|
+
credential: options.credential.trim(),
|
|
17
|
+
address,
|
|
18
|
+
baseUrl: options.baseUrl,
|
|
19
|
+
fetchImpl: options.fetchImpl,
|
|
20
|
+
};
|
|
21
|
+
const client = new CustodyServiceClient(clientOptions);
|
|
22
|
+
return major === 6
|
|
23
|
+
? createEthersV6Signer(options.ethers, address, options.provider, client)
|
|
24
|
+
: createEthersV5Signer(options.ethers, address, options.provider, client);
|
|
25
|
+
}
|
|
26
|
+
function createEthersV6Signer(ethersRuntime, address, provider, client) {
|
|
27
|
+
const AbstractSigner = requireRuntimeConstructor(ethersRuntime, 'AbstractSigner');
|
|
28
|
+
const Transaction = requireRuntimeConstructor(ethersRuntime, 'Transaction');
|
|
29
|
+
return new (class CustodyEthersV6Signer extends AbstractSigner {
|
|
30
|
+
address = address;
|
|
31
|
+
constructor(connectedProvider) {
|
|
32
|
+
super(connectedProvider);
|
|
33
|
+
}
|
|
34
|
+
async getAddress() {
|
|
35
|
+
return this.address;
|
|
36
|
+
}
|
|
37
|
+
connect(connectedProvider) {
|
|
38
|
+
return new CustodyEthersV6Signer(connectedProvider);
|
|
39
|
+
}
|
|
40
|
+
async signTransaction(transactionRequest) {
|
|
41
|
+
assertTransactionFrom(ethersRuntime, 6, transactionRequest.from, this.address);
|
|
42
|
+
const transactionInput = transactionRequest instanceof Transaction
|
|
43
|
+
? transactionRequest
|
|
44
|
+
: { ...transactionRequest };
|
|
45
|
+
if (!(transactionRequest instanceof Transaction)) {
|
|
46
|
+
delete transactionInput.from;
|
|
47
|
+
}
|
|
48
|
+
let unsignedTransaction;
|
|
49
|
+
try {
|
|
50
|
+
unsignedTransaction = Transaction.from(transactionInput);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
throw new Error('交易必须是字段完整且地址已解析的未签名交易');
|
|
54
|
+
}
|
|
55
|
+
if (unsignedTransaction.signature) {
|
|
56
|
+
throw new Error('交易必须是未签名交易');
|
|
57
|
+
}
|
|
58
|
+
const result = await client.signTransaction({
|
|
59
|
+
transaction: unsignedTransaction.toJSON(),
|
|
60
|
+
chainId: unsignedTransaction.chainId.toString(),
|
|
61
|
+
});
|
|
62
|
+
const serialized = requireResponseString(result, 'signedTransaction');
|
|
63
|
+
let signedTransaction;
|
|
64
|
+
try {
|
|
65
|
+
signedTransaction = Transaction.from(serialized);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
throw new Error('托管服务返回了无效的已签名交易');
|
|
69
|
+
}
|
|
70
|
+
if (!signedTransaction.signature || !signedTransaction.from) {
|
|
71
|
+
throw new Error('托管服务返回的交易缺少有效签名');
|
|
72
|
+
}
|
|
73
|
+
if (signedTransaction.unsignedHash !== unsignedTransaction.unsignedHash) {
|
|
74
|
+
throw new Error('托管服务返回的交易与原始交易不一致');
|
|
75
|
+
}
|
|
76
|
+
assertRecoveredAddress(ethersRuntime, 6, signedTransaction.from, this.address);
|
|
77
|
+
return signedTransaction.serialized;
|
|
78
|
+
}
|
|
79
|
+
async signMessage(message) {
|
|
80
|
+
const result = await client.signMessage(typeof message === 'string'
|
|
81
|
+
? { message }
|
|
82
|
+
: { messageHex: ethersRuntime.hexlify(message) });
|
|
83
|
+
const signature = normalizeV6Signature(ethersRuntime, result);
|
|
84
|
+
assertRecoveredAddress(ethersRuntime, 6, ethersRuntime.verifyMessage(message, signature), this.address);
|
|
85
|
+
return signature;
|
|
86
|
+
}
|
|
87
|
+
async signTypedData(domain, types, value) {
|
|
88
|
+
const result = await client.signTypedData({ domain, types, value });
|
|
89
|
+
const signature = normalizeV6Signature(ethersRuntime, result);
|
|
90
|
+
assertRecoveredAddress(ethersRuntime, 6, ethersRuntime.verifyTypedData(domain, types, value, signature), this.address);
|
|
91
|
+
return signature;
|
|
92
|
+
}
|
|
93
|
+
})(provider);
|
|
94
|
+
}
|
|
95
|
+
function createEthersV5Signer(ethersRuntime, address, provider, client) {
|
|
96
|
+
const Signer = requireRuntimeConstructor(ethersRuntime, 'Signer');
|
|
97
|
+
const utils = requireRuntimeObject(ethersRuntime, 'utils');
|
|
98
|
+
return new (class CustodyEthersV5Signer extends Signer {
|
|
99
|
+
address = address;
|
|
100
|
+
constructor(connectedProvider) {
|
|
101
|
+
super();
|
|
102
|
+
Object.defineProperty(this, 'provider', {
|
|
103
|
+
value: connectedProvider,
|
|
104
|
+
enumerable: true,
|
|
105
|
+
configurable: false,
|
|
106
|
+
writable: false,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async getAddress() {
|
|
110
|
+
return this.address;
|
|
111
|
+
}
|
|
112
|
+
connect(connectedProvider) {
|
|
113
|
+
return new CustodyEthersV5Signer(connectedProvider);
|
|
114
|
+
}
|
|
115
|
+
async signTransaction(transactionRequest) {
|
|
116
|
+
const resolvedRequest = await utils.resolveProperties(transactionRequest);
|
|
117
|
+
assertTransactionFrom(ethersRuntime, 5, resolvedRequest.from, this.address);
|
|
118
|
+
const unsignedTransaction = selectV5TransactionFields(resolvedRequest);
|
|
119
|
+
let unsignedSerialized;
|
|
120
|
+
try {
|
|
121
|
+
unsignedSerialized = utils.serializeTransaction(unsignedTransaction);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
throw new Error('交易必须是字段完整且地址已解析的未签名交易');
|
|
125
|
+
}
|
|
126
|
+
const result = await client.signTransaction({
|
|
127
|
+
transaction: serializeV5TransactionForService(unsignedTransaction),
|
|
128
|
+
chainId: String(unsignedTransaction.chainId),
|
|
129
|
+
});
|
|
130
|
+
const serialized = requireResponseString(result, 'signedTransaction');
|
|
131
|
+
let signedTransaction;
|
|
132
|
+
try {
|
|
133
|
+
signedTransaction = utils.parseTransaction(serialized);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
throw new Error('托管服务返回了无效的已签名交易');
|
|
137
|
+
}
|
|
138
|
+
if (!signedTransaction.from || !signedTransaction.r || !signedTransaction.s) {
|
|
139
|
+
throw new Error('托管服务返回的交易缺少有效签名');
|
|
140
|
+
}
|
|
141
|
+
const returnedUnsigned = utils.serializeTransaction(selectV5TransactionFields(signedTransaction));
|
|
142
|
+
if (returnedUnsigned.toLowerCase() !== unsignedSerialized.toLowerCase()) {
|
|
143
|
+
throw new Error('托管服务返回的交易与原始交易不一致');
|
|
144
|
+
}
|
|
145
|
+
assertRecoveredAddress(ethersRuntime, 5, signedTransaction.from, this.address);
|
|
146
|
+
return serialized;
|
|
147
|
+
}
|
|
148
|
+
async signMessage(message) {
|
|
149
|
+
const result = await client.signMessage(typeof message === 'string'
|
|
150
|
+
? { message }
|
|
151
|
+
: { messageHex: utils.hexlify(message) });
|
|
152
|
+
const signature = normalizeV5Signature(utils, result);
|
|
153
|
+
assertRecoveredAddress(ethersRuntime, 5, utils.verifyMessage(message, signature), this.address);
|
|
154
|
+
return signature;
|
|
155
|
+
}
|
|
156
|
+
async _signTypedData(domain, types, value) {
|
|
157
|
+
const result = await client.signTypedData({ domain, types, value });
|
|
158
|
+
const signature = normalizeV5Signature(utils, result);
|
|
159
|
+
assertRecoveredAddress(ethersRuntime, 5, utils.verifyTypedData(domain, types, value, signature), this.address);
|
|
160
|
+
return signature;
|
|
161
|
+
}
|
|
162
|
+
})(provider);
|
|
163
|
+
}
|
|
164
|
+
function selectV5TransactionFields(transaction) {
|
|
165
|
+
const result = {};
|
|
166
|
+
for (const field of [
|
|
167
|
+
'type',
|
|
168
|
+
'chainId',
|
|
169
|
+
'nonce',
|
|
170
|
+
'to',
|
|
171
|
+
'value',
|
|
172
|
+
'gasLimit',
|
|
173
|
+
'gasPrice',
|
|
174
|
+
'data',
|
|
175
|
+
'accessList',
|
|
176
|
+
'maxFeePerGas',
|
|
177
|
+
'maxPriorityFeePerGas',
|
|
178
|
+
]) {
|
|
179
|
+
if (transaction[field] !== undefined && transaction[field] !== null) {
|
|
180
|
+
result[field] = transaction[field];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
function serializeV5TransactionForService(transaction) {
|
|
186
|
+
const result = {};
|
|
187
|
+
for (const [field, value] of Object.entries(transaction)) {
|
|
188
|
+
if (value !== null &&
|
|
189
|
+
typeof value === 'object' &&
|
|
190
|
+
typeof value.toString === 'function' &&
|
|
191
|
+
['chainId', 'nonce', 'value', 'gasLimit', 'gasPrice', 'maxFeePerGas', 'maxPriorityFeePerGas'].includes(field)) {
|
|
192
|
+
result[field] = value.toString();
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
result[field] = value;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
function normalizeV6Signature(ethersRuntime, payload) {
|
|
201
|
+
const value = requireResponseString(payload, 'signature');
|
|
202
|
+
try {
|
|
203
|
+
return ethersRuntime.Signature.from(value).serialized;
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
throw new Error('托管服务返回了无效签名');
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function normalizeV5Signature(utils, payload) {
|
|
210
|
+
const value = requireResponseString(payload, 'signature');
|
|
211
|
+
try {
|
|
212
|
+
return utils.joinSignature(utils.splitSignature(value));
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
throw new Error('托管服务返回了无效签名');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function assertTransactionFrom(ethersRuntime, major, from, expectedAddress) {
|
|
219
|
+
if (from === undefined || from === null) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (typeof from !== 'string') {
|
|
223
|
+
throw new Error('交易 from 必须是已解析的钱包地址');
|
|
224
|
+
}
|
|
225
|
+
assertRecoveredAddress(ethersRuntime, major, from, expectedAddress);
|
|
226
|
+
}
|
|
227
|
+
function assertRecoveredAddress(ethersRuntime, major, actual, expected) {
|
|
228
|
+
let normalizedActual;
|
|
229
|
+
try {
|
|
230
|
+
normalizedActual = normalizeAddress(ethersRuntime, major, actual);
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
throw new Error('托管服务返回的签名地址无效');
|
|
234
|
+
}
|
|
235
|
+
if (normalizedActual !== expected) {
|
|
236
|
+
throw new Error('托管服务返回的签名地址与配置钱包地址不一致');
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function normalizeAddress(ethersRuntime, major, address) {
|
|
240
|
+
return major === 6
|
|
241
|
+
? ethersRuntime.getAddress(address)
|
|
242
|
+
: requireRuntimeObject(ethersRuntime, 'utils').getAddress(address);
|
|
243
|
+
}
|
|
244
|
+
function requireRuntimeConstructor(ethersRuntime, field) {
|
|
245
|
+
const value = ethersRuntime[field];
|
|
246
|
+
if (typeof value !== 'function') {
|
|
247
|
+
throw new Error(`当前 ethers runtime 缺少 ${field}`);
|
|
248
|
+
}
|
|
249
|
+
return value;
|
|
250
|
+
}
|
|
251
|
+
function requireRuntimeObject(ethersRuntime, field) {
|
|
252
|
+
const value = ethersRuntime[field];
|
|
253
|
+
if (typeof value !== 'object' || value === null) {
|
|
254
|
+
throw new Error(`当前 ethers runtime 缺少 ${field}`);
|
|
255
|
+
}
|
|
256
|
+
return value;
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=signer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signer.js","sourceRoot":"","sources":["../../src/custody/signer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/custody/version.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,aAAa,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,CAAC,GAAG,CAAC,CAa7E"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function detectEthersMajor(ethersRuntime) {
|
|
2
|
+
const { version } = ethersRuntime;
|
|
3
|
+
if (typeof version !== 'string') {
|
|
4
|
+
throw new Error('无法识别当前 ethers 版本');
|
|
5
|
+
}
|
|
6
|
+
const match = /^(?:ethers\/)?(\d+)(?:\.|$)/.exec(version.trim());
|
|
7
|
+
const major = match === null ? Number.NaN : Number.parseInt(match[1], 10);
|
|
8
|
+
if (major === 5 || major === 6) {
|
|
9
|
+
return major;
|
|
10
|
+
}
|
|
11
|
+
throw new Error(`不支持的 ethers 版本:${version}`);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/custody/version.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,iBAAiB,CAAC,aAAoC;IACpE,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC;IAClC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,KAAK,GAAG,6BAA6B,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1E,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,kBAAkB,OAAO,EAAE,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROJECT_SECRET_PATTERN = exports.PRIVATE_KEY_PATTERN = void 0;
|
|
4
|
+
exports.parseWalletCredential = parseWalletCredential;
|
|
5
|
+
exports.resolveWalletCredential = resolveWalletCredential;
|
|
6
|
+
exports.resolveHardhatAccounts = resolveHardhatAccounts;
|
|
7
|
+
exports.PRIVATE_KEY_PATTERN = /^(?:0x)?[0-9a-fA-F]{64}$/;
|
|
8
|
+
exports.PROJECT_SECRET_PATTERN = /^sk-(?:test|live)-[A-Z0-9_-]+\.[A-Za-z0-9_-]{32}$/;
|
|
9
|
+
const ADDRESS_PATTERN = /^0x[0-9a-fA-F]{40}$/;
|
|
10
|
+
const ZERO_ADDRESS = /^0x0{40}$/i;
|
|
11
|
+
const CUSTODY_PREFIX = 'custody:';
|
|
12
|
+
function parseWalletCredential(value) {
|
|
13
|
+
const credential = value.trim();
|
|
14
|
+
if (exports.PRIVATE_KEY_PATTERN.test(credential)) {
|
|
15
|
+
return {
|
|
16
|
+
kind: 'private-key',
|
|
17
|
+
privateKey: credential.startsWith('0x')
|
|
18
|
+
? credential
|
|
19
|
+
: `0x${credential}`,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (credential.startsWith(CUSTODY_PREFIX)) {
|
|
23
|
+
return parseCustodyCredential(credential);
|
|
24
|
+
}
|
|
25
|
+
throw new Error('不支持的钱包凭证格式:请传入 64 位十六进制私钥或 custody 凭证');
|
|
26
|
+
}
|
|
27
|
+
function resolveWalletCredential(env = process.env) {
|
|
28
|
+
const unified = normalizeOptionalValue(env.WALLET_CREDENTIAL);
|
|
29
|
+
const legacy = normalizeOptionalValue(env.PRIVATE_KEY);
|
|
30
|
+
if (unified !== undefined && legacy !== undefined && unified !== legacy) {
|
|
31
|
+
throw new Error('WALLET_CREDENTIAL 与 PRIVATE_KEY 配置冲突');
|
|
32
|
+
}
|
|
33
|
+
const value = unified ?? legacy;
|
|
34
|
+
return value === undefined ? undefined : parseWalletCredential(value);
|
|
35
|
+
}
|
|
36
|
+
function resolveHardhatAccounts(value) {
|
|
37
|
+
const normalized = normalizeOptionalValue(value);
|
|
38
|
+
if (normalized === undefined) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
const credential = parseWalletCredential(normalized);
|
|
42
|
+
return credential.kind === 'private-key' ? [credential.privateKey] : [];
|
|
43
|
+
}
|
|
44
|
+
function parseCustodyCredential(value) {
|
|
45
|
+
const remainder = value.slice(CUSTODY_PREFIX.length);
|
|
46
|
+
const separatorIndex = remainder.lastIndexOf(':');
|
|
47
|
+
if (separatorIndex <= 0) {
|
|
48
|
+
throw new Error('托管钱包凭证格式无效');
|
|
49
|
+
}
|
|
50
|
+
const secret = remainder.slice(0, separatorIndex);
|
|
51
|
+
const address = remainder.slice(separatorIndex + 1);
|
|
52
|
+
if (!exports.PROJECT_SECRET_PATTERN.test(secret)) {
|
|
53
|
+
throw new Error('托管钱包凭证中的 Project Secret 格式无效');
|
|
54
|
+
}
|
|
55
|
+
if (!ADDRESS_PATTERN.test(address)) {
|
|
56
|
+
throw new Error('托管钱包凭证中的钱包地址格式无效');
|
|
57
|
+
}
|
|
58
|
+
if (ZERO_ADDRESS.test(address)) {
|
|
59
|
+
throw new Error('托管钱包地址不能是零地址');
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
kind: 'custody',
|
|
63
|
+
secret,
|
|
64
|
+
address,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function normalizeOptionalValue(value) {
|
|
68
|
+
if (value === undefined) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const normalized = value.trim();
|
|
72
|
+
return normalized === '' ? undefined : normalized;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=credential.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../../src/custody/credential.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.installCustodyHardhatRuntime = installCustodyHardhatRuntime;
|
|
4
|
+
const credential_js_1 = require("./credential.js");
|
|
5
|
+
const signer_js_1 = require("./signer.js");
|
|
6
|
+
const version_js_1 = require("./version.js");
|
|
7
|
+
const installedEnvironments = new WeakSet();
|
|
8
|
+
function installCustodyHardhatRuntime(hre, options = {}) {
|
|
9
|
+
if (installedEnvironments.has(hre)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const ethersRuntime = hre.ethers;
|
|
13
|
+
if (typeof ethersRuntime !== 'object' ||
|
|
14
|
+
ethersRuntime === null ||
|
|
15
|
+
typeof ethersRuntime.getSigners !== 'function' ||
|
|
16
|
+
typeof ethersRuntime.getSigner !== 'function' ||
|
|
17
|
+
typeof ethersRuntime.provider?.getSigner !== 'function') {
|
|
18
|
+
throw new Error('gate-evm-tools/hardhat 必须在 Hardhat ethers 插件之后加载');
|
|
19
|
+
}
|
|
20
|
+
const env = options.env ?? process.env;
|
|
21
|
+
const logger = options.logger ?? ((message) => console.info(message));
|
|
22
|
+
const originalGetSigners = ethersRuntime.getSigners;
|
|
23
|
+
const originalGetSigner = ethersRuntime.getSigner;
|
|
24
|
+
const originalProviderGetSigner = ethersRuntime.provider.getSigner;
|
|
25
|
+
let cachedKey;
|
|
26
|
+
let cachedSigner;
|
|
27
|
+
const readCustodyCredential = () => {
|
|
28
|
+
if (env.GATE_MIGRATION_READ_ONLY?.trim() === '1') {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const credential = (0, credential_js_1.resolveWalletCredential)(env);
|
|
32
|
+
return credential?.kind === 'custody' ? credential : undefined;
|
|
33
|
+
};
|
|
34
|
+
const getCustodySigner = (credential) => {
|
|
35
|
+
const baseUrl = env.CUSTODY_API_BASE_URL?.trim();
|
|
36
|
+
if (!baseUrl) {
|
|
37
|
+
throw new Error('托管钱包模式必须配置 CUSTODY_API_BASE_URL');
|
|
38
|
+
}
|
|
39
|
+
const credentialValue = `custody:${credential.secret}:${credential.address}`;
|
|
40
|
+
const cacheKey = `${credentialValue}\n${baseUrl}`;
|
|
41
|
+
if (cachedSigner !== undefined && cachedKey === cacheKey) {
|
|
42
|
+
return cachedSigner;
|
|
43
|
+
}
|
|
44
|
+
cachedSigner = (0, signer_js_1.createSigner)({
|
|
45
|
+
ethers: ethersRuntime,
|
|
46
|
+
credential: credentialValue,
|
|
47
|
+
provider: ethersRuntime.provider,
|
|
48
|
+
baseUrl,
|
|
49
|
+
fetchImpl: options.fetchImpl,
|
|
50
|
+
});
|
|
51
|
+
cachedKey = cacheKey;
|
|
52
|
+
const major = (0, version_js_1.detectEthersMajor)(ethersRuntime);
|
|
53
|
+
logger(`[gate-evm-tools] custody signer enabled (ethers v${major}, ${credential.address})`);
|
|
54
|
+
return cachedSigner;
|
|
55
|
+
};
|
|
56
|
+
ethersRuntime.getSigners = async (...args) => {
|
|
57
|
+
const credential = readCustodyCredential();
|
|
58
|
+
if (credential === undefined) {
|
|
59
|
+
return originalGetSigners.apply(ethersRuntime, args);
|
|
60
|
+
}
|
|
61
|
+
return [getCustodySigner(credential)];
|
|
62
|
+
};
|
|
63
|
+
ethersRuntime.getSigner = async (...args) => {
|
|
64
|
+
const credential = readCustodyCredential();
|
|
65
|
+
const requestedAddress = args[0];
|
|
66
|
+
if (credential !== undefined &&
|
|
67
|
+
typeof requestedAddress === 'string' &&
|
|
68
|
+
addressesMatch(ethersRuntime, credential.address, requestedAddress)) {
|
|
69
|
+
return getCustodySigner(credential);
|
|
70
|
+
}
|
|
71
|
+
return originalGetSigner.apply(ethersRuntime, args);
|
|
72
|
+
};
|
|
73
|
+
ethersRuntime.provider.getSigner = (...args) => {
|
|
74
|
+
const credential = readCustodyCredential();
|
|
75
|
+
const requestedAccount = args[0];
|
|
76
|
+
if (credential !== undefined &&
|
|
77
|
+
(requestedAccount === undefined ||
|
|
78
|
+
requestedAccount === null ||
|
|
79
|
+
requestedAccount === 0 ||
|
|
80
|
+
(typeof requestedAccount === 'string' &&
|
|
81
|
+
addressesMatch(ethersRuntime, credential.address, requestedAccount)))) {
|
|
82
|
+
const signer = getCustodySigner(credential);
|
|
83
|
+
return (0, version_js_1.detectEthersMajor)(ethersRuntime) === 6
|
|
84
|
+
? Promise.resolve(signer)
|
|
85
|
+
: signer;
|
|
86
|
+
}
|
|
87
|
+
return originalProviderGetSigner.apply(ethersRuntime.provider, args);
|
|
88
|
+
};
|
|
89
|
+
installedEnvironments.add(hre);
|
|
90
|
+
}
|
|
91
|
+
function addressesMatch(ethersRuntime, first, second) {
|
|
92
|
+
try {
|
|
93
|
+
const major = (0, version_js_1.detectEthersMajor)(ethersRuntime);
|
|
94
|
+
const getAddress = major === 6 ? ethersRuntime.getAddress : ethersRuntime.utils?.getAddress;
|
|
95
|
+
if (typeof getAddress !== 'function') {
|
|
96
|
+
return first.toLowerCase() === second.toLowerCase();
|
|
97
|
+
}
|
|
98
|
+
return getAddress(first) === getAddress(second);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=hardhat-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hardhat-runtime.js","sourceRoot":"","sources":["../../src/custody/hardhat-runtime.ts"],"names":[],"mappings":";;AAwBA,oEA+GC;AAvID,mDAGyB;AACzB,2CAA2C;AAC3C,6CAAiD;AAiBjD,MAAM,qBAAqB,GAAG,IAAI,OAAO,EAAU,CAAC;AAEpD,SAAgB,4BAA4B,CAC1C,GAAuB,EACvB,UAA+C,EAAE;IAEjD,IAAI,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC;IACjC,IACE,OAAO,aAAa,KAAK,QAAQ;QACjC,aAAa,KAAK,IAAI;QACtB,OAAO,aAAa,CAAC,UAAU,KAAK,UAAU;QAC9C,OAAO,aAAa,CAAC,SAAS,KAAK,UAAU;QAC7C,OAAO,aAAa,CAAC,QAAQ,EAAE,SAAS,KAAK,UAAU,EACvD,CAAC;QACD,MAAM,IAAI,KAAK,CACb,kDAAkD,CACnD,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACvC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9E,MAAM,kBAAkB,GAAG,aAAa,CAAC,UAAU,CAAC;IACpD,MAAM,iBAAiB,GAAG,aAAa,CAAC,SAAS,CAAC;IAClD,MAAM,yBAAyB,GAAG,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC;IACnE,IAAI,SAA6B,CAAC;IAClC,IAAI,YAAiB,CAAC;IAEtB,MAAM,qBAAqB,GAAG,GAAkC,EAAE;QAChE,IAAI,GAAG,CAAC,wBAAwB,EAAE,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACjD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,UAAU,GAAG,IAAA,uCAAuB,EAAC,GAAG,CAAC,CAAC;QAChD,OAAO,UAAU,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,CAAC,UAA6B,EAAO,EAAE;QAC9D,MAAM,OAAO,GAAG,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,eAAe,GACnB,WAAW,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACvD,MAAM,QAAQ,GAAG,GAAG,eAAe,KAAK,OAAO,EAAE,CAAC;QAClD,IAAI,YAAY,KAAK,SAAS,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YACzD,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,YAAY,GAAG,IAAA,wBAAY,EAAC;YAC1B,MAAM,EAAE,aAAa;YACrB,UAAU,EAAE,eAAe;YAC3B,QAAQ,EAAE,aAAa,CAAC,QAAQ;YAChC,OAAO;YACP,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CAAC,CAAC;QACH,SAAS,GAAG,QAAQ,CAAC;QAErB,MAAM,KAAK,GAAG,IAAA,8BAAiB,EAAC,aAAa,CAAC,CAAC;QAC/C,MAAM,CACJ,oDAAoD,KAAK,KAAK,UAAU,CAAC,OAAO,GAAG,CACpF,CAAC;QACF,OAAO,YAAY,CAAC;IACtB,CAAC,CAAC;IAEF,aAAa,CAAC,UAAU,GAAG,KAAK,EAAE,GAAG,IAAW,EAAkB,EAAE;QAClE,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;QAC3C,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,kBAAkB,CAAC,KAAK,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC;IAEF,aAAa,CAAC,SAAS,GAAG,KAAK,EAAE,GAAG,IAAW,EAAgB,EAAE;QAC/D,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;QAC3C,MAAM,gBAAgB,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACjC,IACE,UAAU,KAAK,SAAS;YACxB,OAAO,gBAAgB,KAAK,QAAQ;YACpC,cAAc,CAAC,aAAa,EAAE,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,EACnE,CAAC;YACD,OAAO,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,iBAAiB,CAAC,KAAK,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACtD,CAAC,CAAC;IAEF,aAAa,CAAC,QAAQ,CAAC,SAAS,GAAG,CAAC,GAAG,IAAW,EAAO,EAAE;QACzD,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;QAC3C,MAAM,gBAAgB,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACjC,IACE,UAAU,KAAK,SAAS;YACxB,CAAC,gBAAgB,KAAK,SAAS;gBAC7B,gBAAgB,KAAK,IAAI;gBACzB,gBAAgB,KAAK,CAAC;gBACtB,CAAC,OAAO,gBAAgB,KAAK,QAAQ;oBACnC,cAAc,CACZ,aAAa,EACb,UAAU,CAAC,OAAO,EAClB,gBAAgB,CACjB,CAAC,CAAC,EACP,CAAC;YACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAC5C,OAAO,IAAA,8BAAiB,EAAC,aAAa,CAAC,KAAK,CAAC;gBAC3C,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;gBACzB,CAAC,CAAC,MAAM,CAAC;QACb,CAAC;QACD,OAAO,yBAAyB,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACvE,CAAC,CAAC;IAEF,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,cAAc,CACrB,aAAkC,EAClC,KAAa,EACb,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAA,8BAAiB,EAAC,aAAa,CAAC,CAAC;QAC/C,MAAM,UAAU,GACd,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,UAAU,CAAC;QAC3E,IAAI,OAAO,UAAU,KAAK,UAAU,EAAE,CAAC;YACrC,OAAO,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;QACtD,CAAC;QACD,OAAO,UAAU,CAAC,KAAK,CAAC,KAAK,UAAU,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveWalletCredential = exports.resolveHardhatAccounts = exports.parseWalletCredential = exports.installCustodyHardhatRuntime = void 0;
|
|
4
|
+
const config_js_1 = require("hardhat/config.js");
|
|
5
|
+
const hardhat_runtime_js_1 = require("./hardhat-runtime.js");
|
|
6
|
+
(0, config_js_1.extendEnvironment)((hre) => {
|
|
7
|
+
(0, hardhat_runtime_js_1.installCustodyHardhatRuntime)(hre);
|
|
8
|
+
});
|
|
9
|
+
var hardhat_runtime_js_2 = require("./hardhat-runtime.js");
|
|
10
|
+
Object.defineProperty(exports, "installCustodyHardhatRuntime", { enumerable: true, get: function () { return hardhat_runtime_js_2.installCustodyHardhatRuntime; } });
|
|
11
|
+
var credential_js_1 = require("./credential.js");
|
|
12
|
+
Object.defineProperty(exports, "parseWalletCredential", { enumerable: true, get: function () { return credential_js_1.parseWalletCredential; } });
|
|
13
|
+
Object.defineProperty(exports, "resolveHardhatAccounts", { enumerable: true, get: function () { return credential_js_1.resolveHardhatAccounts; } });
|
|
14
|
+
Object.defineProperty(exports, "resolveWalletCredential", { enumerable: true, get: function () { return credential_js_1.resolveWalletCredential; } });
|
|
15
|
+
//# sourceMappingURL=hardhat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hardhat.js","sourceRoot":"","sources":["../../src/custody/hardhat.ts"],"names":[],"mappings":";;;AAAA,iDAAsD;AAEtD,6DAAoE;AAEpE,IAAA,6BAAiB,EAAC,CAAC,GAAG,EAAE,EAAE;IACxB,IAAA,iDAA4B,EAAC,GAAU,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC;AAEH,2DAG8B;AAF5B,kIAAA,4BAA4B,OAAA;AAG9B,iDAKyB;AAJvB,sHAAA,qBAAqB,OAAA;AACrB,uHAAA,sBAAsB,OAAA;AACtB,wHAAA,uBAAuB,OAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.installCustodyHardhatRuntime = exports.CustodyServiceClient = exports.createSigner = exports.detectEthersMajor = exports.resolveWalletCredential = exports.resolveHardhatAccounts = exports.parseWalletCredential = exports.PROJECT_SECRET_PATTERN = exports.PRIVATE_KEY_PATTERN = void 0;
|
|
4
|
+
var credential_js_1 = require("./credential.js");
|
|
5
|
+
Object.defineProperty(exports, "PRIVATE_KEY_PATTERN", { enumerable: true, get: function () { return credential_js_1.PRIVATE_KEY_PATTERN; } });
|
|
6
|
+
Object.defineProperty(exports, "PROJECT_SECRET_PATTERN", { enumerable: true, get: function () { return credential_js_1.PROJECT_SECRET_PATTERN; } });
|
|
7
|
+
Object.defineProperty(exports, "parseWalletCredential", { enumerable: true, get: function () { return credential_js_1.parseWalletCredential; } });
|
|
8
|
+
Object.defineProperty(exports, "resolveHardhatAccounts", { enumerable: true, get: function () { return credential_js_1.resolveHardhatAccounts; } });
|
|
9
|
+
Object.defineProperty(exports, "resolveWalletCredential", { enumerable: true, get: function () { return credential_js_1.resolveWalletCredential; } });
|
|
10
|
+
var version_js_1 = require("./version.js");
|
|
11
|
+
Object.defineProperty(exports, "detectEthersMajor", { enumerable: true, get: function () { return version_js_1.detectEthersMajor; } });
|
|
12
|
+
var signer_js_1 = require("./signer.js");
|
|
13
|
+
Object.defineProperty(exports, "createSigner", { enumerable: true, get: function () { return signer_js_1.createSigner; } });
|
|
14
|
+
var service_js_1 = require("./service.js");
|
|
15
|
+
Object.defineProperty(exports, "CustodyServiceClient", { enumerable: true, get: function () { return service_js_1.CustodyServiceClient; } });
|
|
16
|
+
var hardhat_runtime_js_1 = require("./hardhat-runtime.js");
|
|
17
|
+
Object.defineProperty(exports, "installCustodyHardhatRuntime", { enumerable: true, get: function () { return hardhat_runtime_js_1.installCustodyHardhatRuntime; } });
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/custody/index.ts"],"names":[],"mappings":";;;AAAA,iDASyB;AARvB,oHAAA,mBAAmB,OAAA;AACnB,uHAAA,sBAAsB,OAAA;AACtB,sHAAA,qBAAqB,OAAA;AACrB,uHAAA,sBAAsB,OAAA;AACtB,wHAAA,uBAAuB,OAAA;AAKzB,2CAAiD;AAAxC,+GAAA,iBAAiB,OAAA;AAC1B,yCAAqE;AAA5D,yGAAA,YAAY,OAAA;AACrB,2CAGsB;AAFpB,kHAAA,oBAAoB,OAAA;AAGtB,2DAG8B;AAF5B,kIAAA,4BAA4B,OAAA"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CustodyServiceClient = void 0;
|
|
4
|
+
exports.requireResponseString = requireResponseString;
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
class CustodyServiceClient {
|
|
7
|
+
#credential;
|
|
8
|
+
#address;
|
|
9
|
+
#baseUrl;
|
|
10
|
+
#fetchImpl;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.#credential = options.credential;
|
|
13
|
+
this.#address = options.address;
|
|
14
|
+
this.#baseUrl = normalizeBaseUrl(options.baseUrl);
|
|
15
|
+
this.#fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
16
|
+
if (typeof this.#fetchImpl !== 'function') {
|
|
17
|
+
throw new Error('当前运行环境不支持 fetch,请显式传入 fetchImpl');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
signTransaction(body) {
|
|
21
|
+
return this.#post('sign-transaction', body);
|
|
22
|
+
}
|
|
23
|
+
signMessage(body) {
|
|
24
|
+
return this.#post('sign-message', body);
|
|
25
|
+
}
|
|
26
|
+
signTypedData(body) {
|
|
27
|
+
return this.#post('sign-typed-data', body);
|
|
28
|
+
}
|
|
29
|
+
async #post(operation, body) {
|
|
30
|
+
const path = `/api/custody/wallets/${encodeURIComponent(this.#address)}/${operation}`;
|
|
31
|
+
let response;
|
|
32
|
+
try {
|
|
33
|
+
response = await this.#fetchImpl(`${this.#baseUrl}${path}`, {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: {
|
|
36
|
+
'content-type': 'application/json',
|
|
37
|
+
authorization: `Bearer ${this.#credential}`,
|
|
38
|
+
'idempotency-key': (0, node_crypto_1.randomUUID)(),
|
|
39
|
+
},
|
|
40
|
+
body: stringifyJson(body),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new Error('无法连接托管签名服务', { cause: error });
|
|
45
|
+
}
|
|
46
|
+
const payload = await readJsonResponse(response);
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
const message = typeof payload.error === 'string'
|
|
49
|
+
? payload.error
|
|
50
|
+
: `托管签名请求失败(HTTP ${response.status})`;
|
|
51
|
+
throw new Error(message);
|
|
52
|
+
}
|
|
53
|
+
return payload;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.CustodyServiceClient = CustodyServiceClient;
|
|
57
|
+
function requireResponseString(payload, field) {
|
|
58
|
+
const value = payload[field];
|
|
59
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
60
|
+
throw new Error(`托管服务响应缺少 ${field}`);
|
|
61
|
+
}
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
async function readJsonResponse(response) {
|
|
65
|
+
let payload;
|
|
66
|
+
try {
|
|
67
|
+
payload = await response.json();
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
throw new Error(`托管签名服务返回了无效 JSON(HTTP ${response.status})`);
|
|
71
|
+
}
|
|
72
|
+
if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) {
|
|
73
|
+
throw new Error(`托管签名服务返回了无效响应(HTTP ${response.status})`);
|
|
74
|
+
}
|
|
75
|
+
return payload;
|
|
76
|
+
}
|
|
77
|
+
function normalizeBaseUrl(baseUrl) {
|
|
78
|
+
if (baseUrl === undefined || baseUrl.trim() === '') {
|
|
79
|
+
return '';
|
|
80
|
+
}
|
|
81
|
+
const normalized = baseUrl.trim();
|
|
82
|
+
if (normalized.includes('?') || normalized.includes('#')) {
|
|
83
|
+
throw invalidBaseUrl();
|
|
84
|
+
}
|
|
85
|
+
let parsed;
|
|
86
|
+
try {
|
|
87
|
+
parsed = new URL(normalized);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
throw invalidBaseUrl();
|
|
91
|
+
}
|
|
92
|
+
if ((parsed.protocol !== 'http:' && parsed.protocol !== 'https:') ||
|
|
93
|
+
parsed.username !== '' ||
|
|
94
|
+
parsed.password !== '') {
|
|
95
|
+
throw invalidBaseUrl();
|
|
96
|
+
}
|
|
97
|
+
return normalized.replace(/\/+$/, '');
|
|
98
|
+
}
|
|
99
|
+
function invalidBaseUrl() {
|
|
100
|
+
return new Error('CUSTODY_API_BASE_URL 必须是无账号、查询参数和片段的 HTTP(S) 地址');
|
|
101
|
+
}
|
|
102
|
+
function stringifyJson(value) {
|
|
103
|
+
return JSON.stringify(value, (_key, fieldValue) => typeof fieldValue === 'bigint' ? fieldValue.toString() : fieldValue);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=service.js.map
|