@weblock-wallet/sdk 0.1.66 → 0.1.68
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/dist/index.cjs +181 -197
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +181 -197
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1778,11 +1778,11 @@ var storage = import_localforage.default.createInstance({
|
|
|
1778
1778
|
description: "WeBlock Wallet SDK Secure Storage"
|
|
1779
1779
|
});
|
|
1780
1780
|
var LocalForage = {
|
|
1781
|
-
async save(key, value,
|
|
1781
|
+
async save(key, value, expiryEpochMs) {
|
|
1782
1782
|
try {
|
|
1783
1783
|
const item = {
|
|
1784
1784
|
value,
|
|
1785
|
-
|
|
1785
|
+
expiryEpochMs
|
|
1786
1786
|
};
|
|
1787
1787
|
await storage.setItem(key, item);
|
|
1788
1788
|
} catch (err) {
|
|
@@ -1792,10 +1792,8 @@ var LocalForage = {
|
|
|
1792
1792
|
async get(key) {
|
|
1793
1793
|
try {
|
|
1794
1794
|
const item = await storage.getItem(key);
|
|
1795
|
-
if (!item)
|
|
1796
|
-
|
|
1797
|
-
}
|
|
1798
|
-
if (item.expiry && Date.now() > item.expiry * 1e3) {
|
|
1795
|
+
if (!item) return null;
|
|
1796
|
+
if (item.expiryEpochMs && Date.now() > item.expiryEpochMs) {
|
|
1799
1797
|
await storage.removeItem(key);
|
|
1800
1798
|
return null;
|
|
1801
1799
|
}
|
|
@@ -1938,26 +1936,6 @@ var AuthService = class {
|
|
|
1938
1936
|
var import_ethers2 = require("ethers");
|
|
1939
1937
|
var import_bip39 = require("bip39");
|
|
1940
1938
|
|
|
1941
|
-
// src/utils/secrets.ts
|
|
1942
|
-
var import_shamir_secret_sharing = require("shamir-secret-sharing");
|
|
1943
|
-
var Secrets = {
|
|
1944
|
-
async split(secret, total, threshold) {
|
|
1945
|
-
if (secret.startsWith("0x")) {
|
|
1946
|
-
secret = secret.substring(2);
|
|
1947
|
-
}
|
|
1948
|
-
const array = await (0, import_shamir_secret_sharing.split)(
|
|
1949
|
-
new Uint8Array(Buffer2.from(secret, "hex")),
|
|
1950
|
-
total,
|
|
1951
|
-
threshold
|
|
1952
|
-
);
|
|
1953
|
-
return array.map((item) => Buffer2.from(item).toString("hex"));
|
|
1954
|
-
},
|
|
1955
|
-
async combine(shares) {
|
|
1956
|
-
const array = shares.map((item) => new Uint8Array(Buffer2.from(item, "hex")));
|
|
1957
|
-
return `0x${Buffer2.from(await (0, import_shamir_secret_sharing.combine)(array)).toString("hex")}`;
|
|
1958
|
-
}
|
|
1959
|
-
};
|
|
1960
|
-
|
|
1961
1939
|
// node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/chunk-CcCWfKp1.js
|
|
1962
1940
|
var exports$22 = {};
|
|
1963
1941
|
var _dewExec$12 = false;
|
|
@@ -103973,6 +103951,26 @@ var webcrypto = exports11.webcrypto;
|
|
|
103973
103951
|
var getRandomValues = exports11.getRandomValues;
|
|
103974
103952
|
var randomUUID = exports11.randomUUID;
|
|
103975
103953
|
|
|
103954
|
+
// src/utils/secrets.ts
|
|
103955
|
+
var import_shamir_secret_sharing = require("shamir-secret-sharing");
|
|
103956
|
+
var Secrets = {
|
|
103957
|
+
async split(secret, total, threshold) {
|
|
103958
|
+
if (secret.startsWith("0x")) {
|
|
103959
|
+
secret = secret.substring(2);
|
|
103960
|
+
}
|
|
103961
|
+
const array = await (0, import_shamir_secret_sharing.split)(
|
|
103962
|
+
new Uint8Array(Buffer2.from(secret, "hex")),
|
|
103963
|
+
total,
|
|
103964
|
+
threshold
|
|
103965
|
+
);
|
|
103966
|
+
return array.map((item) => Buffer2.from(item).toString("hex"));
|
|
103967
|
+
},
|
|
103968
|
+
async combine(shares) {
|
|
103969
|
+
const array = shares.map((item) => new Uint8Array(Buffer2.from(item, "hex")));
|
|
103970
|
+
return `0x${Buffer2.from(await (0, import_shamir_secret_sharing.combine)(array)).toString("hex")}`;
|
|
103971
|
+
}
|
|
103972
|
+
};
|
|
103973
|
+
|
|
103976
103974
|
// src/utils/crypto.ts
|
|
103977
103975
|
var ed = __toESM(require("@noble/ed25519"), 1);
|
|
103978
103976
|
function urlEncode(pemKey) {
|
|
@@ -104020,6 +104018,65 @@ var Crypto = {
|
|
|
104020
104018
|
}
|
|
104021
104019
|
};
|
|
104022
104020
|
|
|
104021
|
+
// src/utils/numbers.ts
|
|
104022
|
+
var import_ethers = require("ethers");
|
|
104023
|
+
var TokenAmount = class {
|
|
104024
|
+
/**
|
|
104025
|
+
* Wei 단위의 값을 사용자가 읽을 수 있는 형태로 변환
|
|
104026
|
+
* @param value - Wei 단위의 값 (hex string 또는 decimal string)
|
|
104027
|
+
* @param decimals - 토큰의 소수점 자리수
|
|
104028
|
+
* @returns 변환된 문자열
|
|
104029
|
+
*/
|
|
104030
|
+
static fromWei(value, decimals) {
|
|
104031
|
+
try {
|
|
104032
|
+
return (0, import_ethers.formatUnits)(value, decimals);
|
|
104033
|
+
} catch (error) {
|
|
104034
|
+
console.error("Error converting from wei:", error);
|
|
104035
|
+
return "0.0";
|
|
104036
|
+
}
|
|
104037
|
+
}
|
|
104038
|
+
/**
|
|
104039
|
+
* 사용자 입력값을 Wei 단위로 변환
|
|
104040
|
+
* @param value - 사용자 입력값 (예: "1.5")
|
|
104041
|
+
* @param decimals - 토큰의 소수점 자리수
|
|
104042
|
+
* @returns Wei 단위의 값
|
|
104043
|
+
*/
|
|
104044
|
+
static toWei(value, decimals) {
|
|
104045
|
+
try {
|
|
104046
|
+
return (0, import_ethers.parseUnits)(value, decimals).toString();
|
|
104047
|
+
} catch (error) {
|
|
104048
|
+
console.error("Error converting to wei:", error);
|
|
104049
|
+
return "0";
|
|
104050
|
+
}
|
|
104051
|
+
}
|
|
104052
|
+
/**
|
|
104053
|
+
* 표시용 포맷으로 변환
|
|
104054
|
+
* @param value - Wei 단위의 값
|
|
104055
|
+
* @param decimals - 토큰의 소수점 자리수
|
|
104056
|
+
* @param maxDecimals - 최대 표시할 소수점 자리수 (기본값: 4)
|
|
104057
|
+
* @returns 포맷된 문자열
|
|
104058
|
+
*/
|
|
104059
|
+
static format(value, decimals, maxDecimals = 4) {
|
|
104060
|
+
const fullNumber = this.fromWei(value, decimals);
|
|
104061
|
+
const [beforeDecimal, afterDecimal = ""] = fullNumber.split(".");
|
|
104062
|
+
return `${beforeDecimal}.${afterDecimal.slice(0, maxDecimals)}`;
|
|
104063
|
+
}
|
|
104064
|
+
/**
|
|
104065
|
+
* 값이 유효한지 검증
|
|
104066
|
+
* @param value - 검증할 값
|
|
104067
|
+
* @returns 유효성 여부
|
|
104068
|
+
*/
|
|
104069
|
+
static isValid(value) {
|
|
104070
|
+
return /^\d*\.?\d*$/.test(value) && value !== "";
|
|
104071
|
+
}
|
|
104072
|
+
};
|
|
104073
|
+
var DECIMALS = {
|
|
104074
|
+
ETH: 18,
|
|
104075
|
+
USDC: 6,
|
|
104076
|
+
USDT: 6,
|
|
104077
|
+
DAI: 18
|
|
104078
|
+
};
|
|
104079
|
+
|
|
104023
104080
|
// src/types/error.ts
|
|
104024
104081
|
var SDKErrorCode = /* @__PURE__ */ ((SDKErrorCode2) => {
|
|
104025
104082
|
SDKErrorCode2["NOT_INITIALIZED"] = "NOT_INITIALIZED";
|
|
@@ -104088,65 +104145,6 @@ var SignInStatus = /* @__PURE__ */ ((SignInStatus2) => {
|
|
|
104088
104145
|
return SignInStatus2;
|
|
104089
104146
|
})(SignInStatus || {});
|
|
104090
104147
|
|
|
104091
|
-
// src/utils/numbers.ts
|
|
104092
|
-
var import_ethers = require("ethers");
|
|
104093
|
-
var TokenAmount = class {
|
|
104094
|
-
/**
|
|
104095
|
-
* Wei 단위의 값을 사용자가 읽을 수 있는 형태로 변환
|
|
104096
|
-
* @param value - Wei 단위의 값 (hex string 또는 decimal string)
|
|
104097
|
-
* @param decimals - 토큰의 소수점 자리수
|
|
104098
|
-
* @returns 변환된 문자열
|
|
104099
|
-
*/
|
|
104100
|
-
static fromWei(value, decimals) {
|
|
104101
|
-
try {
|
|
104102
|
-
return (0, import_ethers.formatUnits)(value, decimals);
|
|
104103
|
-
} catch (error) {
|
|
104104
|
-
console.error("Error converting from wei:", error);
|
|
104105
|
-
return "0.0";
|
|
104106
|
-
}
|
|
104107
|
-
}
|
|
104108
|
-
/**
|
|
104109
|
-
* 사용자 입력값을 Wei 단위로 변환
|
|
104110
|
-
* @param value - 사용자 입력값 (예: "1.5")
|
|
104111
|
-
* @param decimals - 토큰의 소수점 자리수
|
|
104112
|
-
* @returns Wei 단위의 값
|
|
104113
|
-
*/
|
|
104114
|
-
static toWei(value, decimals) {
|
|
104115
|
-
try {
|
|
104116
|
-
return (0, import_ethers.parseUnits)(value, decimals).toString();
|
|
104117
|
-
} catch (error) {
|
|
104118
|
-
console.error("Error converting to wei:", error);
|
|
104119
|
-
return "0";
|
|
104120
|
-
}
|
|
104121
|
-
}
|
|
104122
|
-
/**
|
|
104123
|
-
* 표시용 포맷으로 변환
|
|
104124
|
-
* @param value - Wei 단위의 값
|
|
104125
|
-
* @param decimals - 토큰의 소수점 자리수
|
|
104126
|
-
* @param maxDecimals - 최대 표시할 소수점 자리수 (기본값: 4)
|
|
104127
|
-
* @returns 포맷된 문자열
|
|
104128
|
-
*/
|
|
104129
|
-
static format(value, decimals, maxDecimals = 4) {
|
|
104130
|
-
const fullNumber = this.fromWei(value, decimals);
|
|
104131
|
-
const [beforeDecimal, afterDecimal = ""] = fullNumber.split(".");
|
|
104132
|
-
return `${beforeDecimal}.${afterDecimal.slice(0, maxDecimals)}`;
|
|
104133
|
-
}
|
|
104134
|
-
/**
|
|
104135
|
-
* 값이 유효한지 검증
|
|
104136
|
-
* @param value - 검증할 값
|
|
104137
|
-
* @returns 유효성 여부
|
|
104138
|
-
*/
|
|
104139
|
-
static isValid(value) {
|
|
104140
|
-
return /^\d*\.?\d*$/.test(value) && value !== "";
|
|
104141
|
-
}
|
|
104142
|
-
};
|
|
104143
|
-
var DECIMALS = {
|
|
104144
|
-
ETH: 18,
|
|
104145
|
-
USDC: 6,
|
|
104146
|
-
USDT: 6,
|
|
104147
|
-
DAI: 18
|
|
104148
|
-
};
|
|
104149
|
-
|
|
104150
104148
|
// src/core/services/wallet.ts
|
|
104151
104149
|
var ERC20_ABI = [
|
|
104152
104150
|
"function balanceOf(address owner) view returns (uint256)",
|
|
@@ -104172,7 +104170,7 @@ var WalletService = class {
|
|
|
104172
104170
|
this.walletAddress = null;
|
|
104173
104171
|
}
|
|
104174
104172
|
/**
|
|
104175
|
-
*
|
|
104173
|
+
* Password/PIN mismatch detection for decrypt errors.
|
|
104176
104174
|
*/
|
|
104177
104175
|
isInvalidPasswordError(error) {
|
|
104178
104176
|
if (!error) return false;
|
|
@@ -104191,9 +104189,8 @@ var WalletService = class {
|
|
|
104191
104189
|
return /^[0-9]{6}$/.test(pin);
|
|
104192
104190
|
}
|
|
104193
104191
|
/**
|
|
104194
|
-
* deviceSecret
|
|
104195
|
-
*
|
|
104196
|
-
* - 서버에는 절대 전달하지 않습니다.
|
|
104192
|
+
* deviceSecret: local-only secret for device recovery material.
|
|
104193
|
+
* This must never be sent to server.
|
|
104197
104194
|
*/
|
|
104198
104195
|
async getOrCreateDeviceSecret() {
|
|
104199
104196
|
const key = STORAGE_KEYS.deviceSecret(this.orgHost);
|
|
@@ -104203,19 +104200,20 @@ var WalletService = class {
|
|
|
104203
104200
|
await LocalForage.save(key, secret);
|
|
104204
104201
|
return secret;
|
|
104205
104202
|
}
|
|
104203
|
+
/**
|
|
104204
|
+
* PATCH APPLIED:
|
|
104205
|
+
* Always overwrite encryptedShare2_device when we have a fresh share2.
|
|
104206
|
+
* Keeping an old device share causes (share1 new + share2 old) => different derived wallet.
|
|
104207
|
+
*/
|
|
104206
104208
|
async ensureDeviceEncryptedShare2(share2Plain, firebaseId) {
|
|
104207
104209
|
const encryptedKey = STORAGE_KEYS.encryptedShare2Device(this.orgHost);
|
|
104208
|
-
const existing = await LocalForage.get(encryptedKey);
|
|
104209
|
-
if (existing) return;
|
|
104210
104210
|
const deviceSecret = await this.getOrCreateDeviceSecret();
|
|
104211
104211
|
const encrypted = Crypto.encryptShare(share2Plain, deviceSecret, firebaseId);
|
|
104212
104212
|
await LocalForage.save(encryptedKey, encrypted);
|
|
104213
104213
|
}
|
|
104214
104214
|
async getAddress() {
|
|
104215
104215
|
try {
|
|
104216
|
-
if (this.walletAddress)
|
|
104217
|
-
return this.walletAddress;
|
|
104218
|
-
}
|
|
104216
|
+
if (this.walletAddress) return this.walletAddress;
|
|
104219
104217
|
const savedAddress = await LocalForage.get(
|
|
104220
104218
|
STORAGE_KEYS.walletAddress(this.orgHost)
|
|
104221
104219
|
);
|
|
@@ -104246,7 +104244,6 @@ var WalletService = class {
|
|
|
104246
104244
|
const firebaseId = await LocalForage.get(
|
|
104247
104245
|
STORAGE_KEYS.firebaseId(this.orgHost)
|
|
104248
104246
|
);
|
|
104249
|
-
console.log("1. FirebaseId:", firebaseId);
|
|
104250
104247
|
if (!firebaseId) {
|
|
104251
104248
|
throw new SDKError("Not logged in", "AUTH_REQUIRED" /* AUTH_REQUIRED */);
|
|
104252
104249
|
}
|
|
@@ -104268,27 +104265,18 @@ var WalletService = class {
|
|
|
104268
104265
|
"WALLET_ALREADY_EXISTS" /* WALLET_ALREADY_EXISTS */
|
|
104269
104266
|
);
|
|
104270
104267
|
}
|
|
104271
|
-
console.log("2. Generating wallet...");
|
|
104272
104268
|
const mnemonic = (0, import_bip39.generateMnemonic)();
|
|
104273
104269
|
const seed = await (0, import_bip39.mnemonicToSeed)(mnemonic);
|
|
104274
104270
|
const wallet = new import_ethers2.Wallet(seed.slice(0, 32).toString("hex"));
|
|
104275
|
-
console.log("3. Wallet created:", {
|
|
104276
|
-
address: wallet.address,
|
|
104277
|
-
publicKey: wallet.signingKey.publicKey
|
|
104278
|
-
});
|
|
104279
|
-
console.log("4. Splitting private key...");
|
|
104280
104271
|
const shares = await Secrets.split(wallet.privateKey, 3, 2);
|
|
104281
104272
|
const [share1, share2, share3] = shares;
|
|
104282
|
-
console.log("6. Encrypting shares...");
|
|
104283
104273
|
const encryptedShare2 = Crypto.encryptShare(share2, password, firebaseId);
|
|
104284
104274
|
const encryptedShare3 = Crypto.encryptShare(share3, password, firebaseId);
|
|
104285
|
-
console.log("8. Saving encryptedShare2 to LocalForage...");
|
|
104286
104275
|
await LocalForage.save(
|
|
104287
104276
|
STORAGE_KEYS.encryptedShare2(this.orgHost),
|
|
104288
104277
|
encryptedShare2
|
|
104289
104278
|
);
|
|
104290
104279
|
await this.ensureDeviceEncryptedShare2(share2, firebaseId);
|
|
104291
|
-
console.log("10. Creating wallet on server...");
|
|
104292
104280
|
await this.walletClient.createWallet({
|
|
104293
104281
|
address: wallet.address,
|
|
104294
104282
|
publicKey: wallet.signingKey.publicKey,
|
|
@@ -104302,7 +104290,6 @@ var WalletService = class {
|
|
|
104302
104290
|
);
|
|
104303
104291
|
return wallet.address;
|
|
104304
104292
|
} catch (error) {
|
|
104305
|
-
console.error("Error in create wallet:", error);
|
|
104306
104293
|
if (error instanceof SDKError) throw error;
|
|
104307
104294
|
throw new SDKError(
|
|
104308
104295
|
"Failed to create wallet",
|
|
@@ -104357,8 +104344,13 @@ var WalletService = class {
|
|
|
104357
104344
|
share2 = decryptShareOrThrow(encryptedShare2);
|
|
104358
104345
|
await LocalForage.save(STORAGE_KEYS.share2(this.orgHost), share2);
|
|
104359
104346
|
} else {
|
|
104360
|
-
const share3 = decryptShareOrThrow(
|
|
104361
|
-
|
|
104347
|
+
const share3 = decryptShareOrThrow(
|
|
104348
|
+
walletInfo.encryptedShare3
|
|
104349
|
+
);
|
|
104350
|
+
const privateKey2 = await Secrets.combine([
|
|
104351
|
+
walletInfo.share1,
|
|
104352
|
+
share3
|
|
104353
|
+
]);
|
|
104362
104354
|
const wallet2 = new import_ethers2.Wallet(privateKey2);
|
|
104363
104355
|
const newShares = await Secrets.split(wallet2.privateKey, 3, 2);
|
|
104364
104356
|
const [newShare1, newShare2, newShare3] = newShares;
|
|
@@ -104385,7 +104377,10 @@ var WalletService = class {
|
|
|
104385
104377
|
return wallet2.address;
|
|
104386
104378
|
}
|
|
104387
104379
|
}
|
|
104388
|
-
const privateKey = await Secrets.combine([
|
|
104380
|
+
const privateKey = await Secrets.combine([
|
|
104381
|
+
walletInfo.share1,
|
|
104382
|
+
share2
|
|
104383
|
+
]);
|
|
104389
104384
|
const wallet = new import_ethers2.Wallet(privateKey);
|
|
104390
104385
|
await this.ensureDeviceEncryptedShare2(share2, firebaseId);
|
|
104391
104386
|
this.walletAddress = wallet.address;
|
|
@@ -104398,7 +104393,6 @@ var WalletService = class {
|
|
|
104398
104393
|
} catch (error) {
|
|
104399
104394
|
this.walletAddress = null;
|
|
104400
104395
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104401
|
-
console.error("Error in retrieveWallet:", error);
|
|
104402
104396
|
if (error instanceof SDKError) throw error;
|
|
104403
104397
|
throw new SDKError(
|
|
104404
104398
|
"Failed to retrieve wallet",
|
|
@@ -104408,9 +104402,7 @@ var WalletService = class {
|
|
|
104408
104402
|
}
|
|
104409
104403
|
}
|
|
104410
104404
|
/**
|
|
104411
|
-
*
|
|
104412
|
-
* - 같은 디바이스에 남아있는 encryptedShare2_device를 이용
|
|
104413
|
-
* - 서버는 PATCH /v1/wallets/keys 로 share1 / encryptedShare3 만 업데이트
|
|
104405
|
+
* PIN reset (same private key/address) using encryptedShare2_device.
|
|
104414
104406
|
*/
|
|
104415
104407
|
async resetPin(newPassword) {
|
|
104416
104408
|
try {
|
|
@@ -104435,16 +104427,10 @@ var WalletService = class {
|
|
|
104435
104427
|
const encryptedDevice = await LocalForage.get(
|
|
104436
104428
|
STORAGE_KEYS.encryptedShare2Device(this.orgHost)
|
|
104437
104429
|
);
|
|
104438
|
-
if (!encryptedDevice) {
|
|
104439
|
-
throw new SDKError(
|
|
104440
|
-
"PIN reset is not available on this device",
|
|
104441
|
-
"RECOVERY_NOT_AVAILABLE" /* RECOVERY_NOT_AVAILABLE */
|
|
104442
|
-
);
|
|
104443
|
-
}
|
|
104444
104430
|
const deviceSecret = await LocalForage.get(
|
|
104445
104431
|
STORAGE_KEYS.deviceSecret(this.orgHost)
|
|
104446
104432
|
);
|
|
104447
|
-
if (!deviceSecret) {
|
|
104433
|
+
if (!encryptedDevice || !deviceSecret) {
|
|
104448
104434
|
throw new SDKError(
|
|
104449
104435
|
"PIN reset is not available on this device",
|
|
104450
104436
|
"RECOVERY_NOT_AVAILABLE" /* RECOVERY_NOT_AVAILABLE */
|
|
@@ -104461,7 +104447,10 @@ var WalletService = class {
|
|
|
104461
104447
|
);
|
|
104462
104448
|
}
|
|
104463
104449
|
const walletInfo = await this.walletClient.getWallet();
|
|
104464
|
-
const privateKey = await Secrets.combine([
|
|
104450
|
+
const privateKey = await Secrets.combine([
|
|
104451
|
+
walletInfo.share1,
|
|
104452
|
+
share2
|
|
104453
|
+
]);
|
|
104465
104454
|
const wallet = new import_ethers2.Wallet(privateKey);
|
|
104466
104455
|
const newShares = await Secrets.split(wallet.privateKey, 3, 2);
|
|
104467
104456
|
const [newShare1, newShare2, newShare3] = newShares;
|
|
@@ -104477,15 +104466,7 @@ var WalletService = class {
|
|
|
104477
104466
|
STORAGE_KEYS.encryptedShare2(this.orgHost),
|
|
104478
104467
|
Crypto.encryptShare(newShare2, newPassword, firebaseId)
|
|
104479
104468
|
);
|
|
104480
|
-
|
|
104481
|
-
newShare2,
|
|
104482
|
-
deviceSecret,
|
|
104483
|
-
firebaseId
|
|
104484
|
-
);
|
|
104485
|
-
await LocalForage.save(
|
|
104486
|
-
STORAGE_KEYS.encryptedShare2Device(this.orgHost),
|
|
104487
|
-
newEncryptedDevice
|
|
104488
|
-
);
|
|
104469
|
+
await this.ensureDeviceEncryptedShare2(newShare2, firebaseId);
|
|
104489
104470
|
this.walletAddress = wallet.address;
|
|
104490
104471
|
await LocalForage.save(
|
|
104491
104472
|
STORAGE_KEYS.walletAddress(this.orgHost),
|
|
@@ -104494,7 +104475,6 @@ var WalletService = class {
|
|
|
104494
104475
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104495
104476
|
return wallet.address;
|
|
104496
104477
|
} catch (error) {
|
|
104497
|
-
console.error("Error in resetPin:", error);
|
|
104498
104478
|
if (error instanceof SDKError) throw error;
|
|
104499
104479
|
throw new SDKError(
|
|
104500
104480
|
"Failed to reset PIN",
|
|
@@ -104532,38 +104512,20 @@ var WalletService = class {
|
|
|
104532
104512
|
const rawBalance = await this.rpcClient.sendRpc({
|
|
104533
104513
|
chainId,
|
|
104534
104514
|
method: "eth_call" /* ETH_CALL */,
|
|
104535
|
-
params: [
|
|
104536
|
-
{
|
|
104537
|
-
to: tokenAddress,
|
|
104538
|
-
data
|
|
104539
|
-
},
|
|
104540
|
-
"latest"
|
|
104541
|
-
]
|
|
104515
|
+
params: [{ to: tokenAddress, data }, "latest"]
|
|
104542
104516
|
});
|
|
104543
104517
|
const decimalsData = erc20.encodeFunctionData("decimals", []);
|
|
104544
104518
|
const decimalsRes = await this.rpcClient.sendRpc({
|
|
104545
104519
|
chainId,
|
|
104546
104520
|
method: "eth_call" /* ETH_CALL */,
|
|
104547
|
-
params: [
|
|
104548
|
-
{
|
|
104549
|
-
to: tokenAddress,
|
|
104550
|
-
data: decimalsData
|
|
104551
|
-
},
|
|
104552
|
-
"latest"
|
|
104553
|
-
]
|
|
104521
|
+
params: [{ to: tokenAddress, data: decimalsData }, "latest"]
|
|
104554
104522
|
});
|
|
104555
104523
|
const decimals = parseInt(decimalsRes.result, 16);
|
|
104556
104524
|
const symbolData = erc20.encodeFunctionData("symbol", []);
|
|
104557
104525
|
const symbolRes = await this.rpcClient.sendRpc({
|
|
104558
104526
|
chainId,
|
|
104559
104527
|
method: "eth_call" /* ETH_CALL */,
|
|
104560
|
-
params: [
|
|
104561
|
-
{
|
|
104562
|
-
to: tokenAddress,
|
|
104563
|
-
data: symbolData
|
|
104564
|
-
},
|
|
104565
|
-
"latest"
|
|
104566
|
-
]
|
|
104528
|
+
params: [{ to: tokenAddress, data: symbolData }, "latest"]
|
|
104567
104529
|
});
|
|
104568
104530
|
const symbol = erc20.decodeFunctionResult("symbol", symbolRes.result)[0];
|
|
104569
104531
|
return {
|
|
@@ -104652,34 +104614,36 @@ var WalletService = class {
|
|
|
104652
104614
|
method: "eth_getTransactionCount" /* ETH_GET_TRANSACTION_COUNT */,
|
|
104653
104615
|
params: [address, "latest"]
|
|
104654
104616
|
});
|
|
104655
|
-
if (!nonce.result || nonce.result === "0x0")
|
|
104656
|
-
return void 0;
|
|
104657
|
-
}
|
|
104617
|
+
if (!nonce.result || nonce.result === "0x0") return void 0;
|
|
104658
104618
|
return {
|
|
104659
104619
|
hash: "",
|
|
104660
104620
|
status: "SUCCESS" /* SUCCESS */,
|
|
104661
104621
|
timestamp: Date.now(),
|
|
104662
104622
|
value: "0"
|
|
104663
104623
|
};
|
|
104664
|
-
} catch
|
|
104665
|
-
console.error("Failed to get latest transaction:", error);
|
|
104624
|
+
} catch {
|
|
104666
104625
|
return void 0;
|
|
104667
104626
|
}
|
|
104668
104627
|
}
|
|
104628
|
+
/**
|
|
104629
|
+
* PATCH APPLIED (critical):
|
|
104630
|
+
* - Never overwrite cached walletAddress with derived signer address.
|
|
104631
|
+
* - If server/cached address != derived address => throw WALLET_RECOVERY_FAILED.
|
|
104632
|
+
*/
|
|
104669
104633
|
async sendTransaction(params) {
|
|
104634
|
+
const toHexQuantity = (v5) => {
|
|
104635
|
+
if (v5 === void 0 || v5 === null) return "0x0";
|
|
104636
|
+
const s5 = String(v5).trim();
|
|
104637
|
+
if (!s5) return "0x0";
|
|
104638
|
+
if (s5.startsWith("0x") || s5.startsWith("0X")) return s5;
|
|
104639
|
+
try {
|
|
104640
|
+
const bi = BigInt(s5);
|
|
104641
|
+
return "0x" + bi.toString(16);
|
|
104642
|
+
} catch {
|
|
104643
|
+
return s5;
|
|
104644
|
+
}
|
|
104645
|
+
};
|
|
104670
104646
|
try {
|
|
104671
|
-
const toHexQuantity = (v5) => {
|
|
104672
|
-
if (v5 === void 0 || v5 === null) return "0x0";
|
|
104673
|
-
const s5 = String(v5).trim();
|
|
104674
|
-
if (!s5) return "0x0";
|
|
104675
|
-
if (s5.startsWith("0x") || s5.startsWith("0X")) return s5;
|
|
104676
|
-
try {
|
|
104677
|
-
const bi = BigInt(s5);
|
|
104678
|
-
return "0x" + bi.toString(16);
|
|
104679
|
-
} catch {
|
|
104680
|
-
return s5;
|
|
104681
|
-
}
|
|
104682
|
-
};
|
|
104683
104647
|
const walletInfo = await this.walletClient.getWallet();
|
|
104684
104648
|
const share1 = walletInfo?.share1;
|
|
104685
104649
|
let share2 = await LocalForage.get(
|
|
@@ -104716,25 +104680,25 @@ var WalletService = class {
|
|
|
104716
104680
|
const privateKey = await Secrets.combine([share1, share2]);
|
|
104717
104681
|
const wallet = new import_ethers2.Wallet(privateKey);
|
|
104718
104682
|
const from = wallet.address;
|
|
104719
|
-
const
|
|
104720
|
-
|
|
104721
|
-
|
|
104722
|
-
|
|
104723
|
-
|
|
104724
|
-
|
|
104725
|
-
|
|
104726
|
-
|
|
104727
|
-
|
|
104683
|
+
const serverAddress = String(walletInfo?.address ?? "").trim();
|
|
104684
|
+
const cachedAddress = String(
|
|
104685
|
+
await LocalForage.get(
|
|
104686
|
+
STORAGE_KEYS.walletAddress(this.orgHost)
|
|
104687
|
+
) ?? ""
|
|
104688
|
+
).trim();
|
|
104689
|
+
const mismatch = (a5, b4) => a5 && b4 && a5.toLowerCase() !== b4.toLowerCase();
|
|
104690
|
+
if (mismatch(serverAddress, from) || mismatch(cachedAddress, from)) {
|
|
104691
|
+
throw new SDKError(
|
|
104692
|
+
`Wallet share mismatch detected. server=${serverAddress || "N/A"} cached=${cachedAddress || "N/A"} derived=${from}. Please re-enter PIN (retrieveWallet/resetPin) to refresh shares.`,
|
|
104693
|
+
"WALLET_RECOVERY_FAILED" /* WALLET_RECOVERY_FAILED */
|
|
104728
104694
|
);
|
|
104729
|
-
this.walletAddress = from;
|
|
104730
|
-
await LocalForage.save(STORAGE_KEYS.walletAddress(this.orgHost), from);
|
|
104731
104695
|
}
|
|
104732
104696
|
const nativeBal = await this.rpcClient.sendRpc({
|
|
104733
104697
|
chainId: params.chainId,
|
|
104734
104698
|
method: "eth_getBalance" /* ETH_GET_BALANCE */,
|
|
104735
104699
|
params: [from, "latest"]
|
|
104736
104700
|
});
|
|
104737
|
-
if (!nativeBal?.result || BigInt(nativeBal.result) ===
|
|
104701
|
+
if (!nativeBal?.result || BigInt(nativeBal.result) === 0n) {
|
|
104738
104702
|
throw new SDKError(
|
|
104739
104703
|
`Insufficient native balance for gas. sender=${from} balance=${nativeBal?.result ?? "0x0"}`,
|
|
104740
104704
|
"TRANSACTION_FAILED" /* TRANSACTION_FAILED */
|
|
@@ -104770,17 +104734,16 @@ var WalletService = class {
|
|
|
104770
104734
|
);
|
|
104771
104735
|
const buffered = Math.max(21e3, Math.ceil(est * 1.2));
|
|
104772
104736
|
gasLimit = "0x" + buffered.toString(16);
|
|
104773
|
-
} catch
|
|
104737
|
+
} catch {
|
|
104774
104738
|
const data = (params.data || "0x").toLowerCase();
|
|
104775
104739
|
const isApprove = data.startsWith("0x095ea7b3");
|
|
104776
104740
|
const fallback = isApprove ? 12e4 : data !== "0x" ? 8e5 : 21e3;
|
|
104777
104741
|
gasLimit = "0x" + fallback.toString(16);
|
|
104778
104742
|
}
|
|
104779
104743
|
}
|
|
104780
|
-
const value = params.value ?? "0";
|
|
104781
104744
|
const signedTx = await wallet.signTransaction({
|
|
104782
104745
|
to: params.to,
|
|
104783
|
-
value,
|
|
104746
|
+
value: params.value ?? "0",
|
|
104784
104747
|
data: params.data || "0x",
|
|
104785
104748
|
chainId: params.chainId,
|
|
104786
104749
|
nonce,
|
|
@@ -104791,12 +104754,10 @@ var WalletService = class {
|
|
|
104791
104754
|
const parsed = import_ethers2.Transaction.from(signedTx);
|
|
104792
104755
|
const derivedFrom = parsed?.from;
|
|
104793
104756
|
if (derivedFrom && String(derivedFrom).toLowerCase() !== from.toLowerCase()) {
|
|
104794
|
-
console.warn(
|
|
104795
|
-
|
|
104796
|
-
|
|
104797
|
-
|
|
104798
|
-
derivedFrom
|
|
104799
|
-
);
|
|
104757
|
+
console.warn("[WalletService] signedTx sender mismatch.", {
|
|
104758
|
+
walletFrom: from,
|
|
104759
|
+
txFrom: derivedFrom
|
|
104760
|
+
});
|
|
104800
104761
|
}
|
|
104801
104762
|
} catch {
|
|
104802
104763
|
}
|
|
@@ -104804,9 +104765,8 @@ var WalletService = class {
|
|
|
104804
104765
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104805
104766
|
return txHash;
|
|
104806
104767
|
} catch (error) {
|
|
104807
|
-
|
|
104808
|
-
|
|
104809
|
-
}
|
|
104768
|
+
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104769
|
+
if (error instanceof SDKError) throw error;
|
|
104810
104770
|
const msg = (() => {
|
|
104811
104771
|
try {
|
|
104812
104772
|
const anyErr = error;
|
|
@@ -104955,10 +104915,26 @@ var HttpClient = class {
|
|
|
104955
104915
|
if (!accessToken) {
|
|
104956
104916
|
throw new SDKError("No access token found", "AUTH_REQUIRED" /* AUTH_REQUIRED */);
|
|
104957
104917
|
}
|
|
104918
|
+
;
|
|
104958
104919
|
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
104959
104920
|
}
|
|
104960
104921
|
return headers;
|
|
104961
104922
|
}
|
|
104923
|
+
async safeReadErrorDetails(response) {
|
|
104924
|
+
const contentType = response.headers.get("content-type") || "";
|
|
104925
|
+
try {
|
|
104926
|
+
if (contentType.includes("application/json")) {
|
|
104927
|
+
return await response.json();
|
|
104928
|
+
}
|
|
104929
|
+
} catch {
|
|
104930
|
+
}
|
|
104931
|
+
try {
|
|
104932
|
+
const text = await response.text();
|
|
104933
|
+
return text || void 0;
|
|
104934
|
+
} catch {
|
|
104935
|
+
return void 0;
|
|
104936
|
+
}
|
|
104937
|
+
}
|
|
104962
104938
|
async request(method, path, data, config2 = {}) {
|
|
104963
104939
|
const headers = await this.getHeaders(config2.needsAccessToken);
|
|
104964
104940
|
const requestInit = {
|
|
@@ -104969,20 +104945,28 @@ var HttpClient = class {
|
|
|
104969
104945
|
},
|
|
104970
104946
|
credentials: config2.credentials
|
|
104971
104947
|
};
|
|
104972
|
-
if (data) {
|
|
104948
|
+
if (data !== void 0) {
|
|
104973
104949
|
requestInit.body = JSON.stringify(data);
|
|
104974
104950
|
}
|
|
104975
104951
|
const response = await fetch(`${this.baseUrl}${path}`, requestInit);
|
|
104976
104952
|
if (!response.ok) {
|
|
104953
|
+
if (config2.needsAccessToken && (response.status === 401 || response.status === 403)) {
|
|
104954
|
+
await LocalForage.delete(`${this.orgHost}:accessToken`);
|
|
104955
|
+
throw new SDKError(
|
|
104956
|
+
`Authentication required (status: ${response.status})`,
|
|
104957
|
+
"AUTH_REQUIRED" /* AUTH_REQUIRED */,
|
|
104958
|
+
await this.safeReadErrorDetails(response)
|
|
104959
|
+
);
|
|
104960
|
+
}
|
|
104977
104961
|
throw new SDKError(
|
|
104978
104962
|
`HTTP error! status: ${response.status}`,
|
|
104979
104963
|
"REQUEST_FAILED" /* REQUEST_FAILED */,
|
|
104980
|
-
await
|
|
104964
|
+
await this.safeReadErrorDetails(response)
|
|
104981
104965
|
);
|
|
104982
104966
|
}
|
|
104983
|
-
if (response.status ===
|
|
104984
|
-
|
|
104985
|
-
|
|
104967
|
+
if (response.status === 204) return void 0;
|
|
104968
|
+
const contentLength = response.headers.get("content-length");
|
|
104969
|
+
if (contentLength === "0") return void 0;
|
|
104986
104970
|
try {
|
|
104987
104971
|
return await response.json();
|
|
104988
104972
|
} catch {
|