@weblock-wallet/sdk 0.1.66 → 0.1.67
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 +148 -186
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +148 -186
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1938,26 +1938,6 @@ var AuthService = class {
|
|
|
1938
1938
|
var import_ethers2 = require("ethers");
|
|
1939
1939
|
var import_bip39 = require("bip39");
|
|
1940
1940
|
|
|
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
1941
|
// node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/chunk-CcCWfKp1.js
|
|
1962
1942
|
var exports$22 = {};
|
|
1963
1943
|
var _dewExec$12 = false;
|
|
@@ -103973,6 +103953,26 @@ var webcrypto = exports11.webcrypto;
|
|
|
103973
103953
|
var getRandomValues = exports11.getRandomValues;
|
|
103974
103954
|
var randomUUID = exports11.randomUUID;
|
|
103975
103955
|
|
|
103956
|
+
// src/utils/secrets.ts
|
|
103957
|
+
var import_shamir_secret_sharing = require("shamir-secret-sharing");
|
|
103958
|
+
var Secrets = {
|
|
103959
|
+
async split(secret, total, threshold) {
|
|
103960
|
+
if (secret.startsWith("0x")) {
|
|
103961
|
+
secret = secret.substring(2);
|
|
103962
|
+
}
|
|
103963
|
+
const array = await (0, import_shamir_secret_sharing.split)(
|
|
103964
|
+
new Uint8Array(Buffer2.from(secret, "hex")),
|
|
103965
|
+
total,
|
|
103966
|
+
threshold
|
|
103967
|
+
);
|
|
103968
|
+
return array.map((item) => Buffer2.from(item).toString("hex"));
|
|
103969
|
+
},
|
|
103970
|
+
async combine(shares) {
|
|
103971
|
+
const array = shares.map((item) => new Uint8Array(Buffer2.from(item, "hex")));
|
|
103972
|
+
return `0x${Buffer2.from(await (0, import_shamir_secret_sharing.combine)(array)).toString("hex")}`;
|
|
103973
|
+
}
|
|
103974
|
+
};
|
|
103975
|
+
|
|
103976
103976
|
// src/utils/crypto.ts
|
|
103977
103977
|
var ed = __toESM(require("@noble/ed25519"), 1);
|
|
103978
103978
|
function urlEncode(pemKey) {
|
|
@@ -104020,6 +104020,65 @@ var Crypto = {
|
|
|
104020
104020
|
}
|
|
104021
104021
|
};
|
|
104022
104022
|
|
|
104023
|
+
// src/utils/numbers.ts
|
|
104024
|
+
var import_ethers = require("ethers");
|
|
104025
|
+
var TokenAmount = class {
|
|
104026
|
+
/**
|
|
104027
|
+
* Wei 단위의 값을 사용자가 읽을 수 있는 형태로 변환
|
|
104028
|
+
* @param value - Wei 단위의 값 (hex string 또는 decimal string)
|
|
104029
|
+
* @param decimals - 토큰의 소수점 자리수
|
|
104030
|
+
* @returns 변환된 문자열
|
|
104031
|
+
*/
|
|
104032
|
+
static fromWei(value, decimals) {
|
|
104033
|
+
try {
|
|
104034
|
+
return (0, import_ethers.formatUnits)(value, decimals);
|
|
104035
|
+
} catch (error) {
|
|
104036
|
+
console.error("Error converting from wei:", error);
|
|
104037
|
+
return "0.0";
|
|
104038
|
+
}
|
|
104039
|
+
}
|
|
104040
|
+
/**
|
|
104041
|
+
* 사용자 입력값을 Wei 단위로 변환
|
|
104042
|
+
* @param value - 사용자 입력값 (예: "1.5")
|
|
104043
|
+
* @param decimals - 토큰의 소수점 자리수
|
|
104044
|
+
* @returns Wei 단위의 값
|
|
104045
|
+
*/
|
|
104046
|
+
static toWei(value, decimals) {
|
|
104047
|
+
try {
|
|
104048
|
+
return (0, import_ethers.parseUnits)(value, decimals).toString();
|
|
104049
|
+
} catch (error) {
|
|
104050
|
+
console.error("Error converting to wei:", error);
|
|
104051
|
+
return "0";
|
|
104052
|
+
}
|
|
104053
|
+
}
|
|
104054
|
+
/**
|
|
104055
|
+
* 표시용 포맷으로 변환
|
|
104056
|
+
* @param value - Wei 단위의 값
|
|
104057
|
+
* @param decimals - 토큰의 소수점 자리수
|
|
104058
|
+
* @param maxDecimals - 최대 표시할 소수점 자리수 (기본값: 4)
|
|
104059
|
+
* @returns 포맷된 문자열
|
|
104060
|
+
*/
|
|
104061
|
+
static format(value, decimals, maxDecimals = 4) {
|
|
104062
|
+
const fullNumber = this.fromWei(value, decimals);
|
|
104063
|
+
const [beforeDecimal, afterDecimal = ""] = fullNumber.split(".");
|
|
104064
|
+
return `${beforeDecimal}.${afterDecimal.slice(0, maxDecimals)}`;
|
|
104065
|
+
}
|
|
104066
|
+
/**
|
|
104067
|
+
* 값이 유효한지 검증
|
|
104068
|
+
* @param value - 검증할 값
|
|
104069
|
+
* @returns 유효성 여부
|
|
104070
|
+
*/
|
|
104071
|
+
static isValid(value) {
|
|
104072
|
+
return /^\d*\.?\d*$/.test(value) && value !== "";
|
|
104073
|
+
}
|
|
104074
|
+
};
|
|
104075
|
+
var DECIMALS = {
|
|
104076
|
+
ETH: 18,
|
|
104077
|
+
USDC: 6,
|
|
104078
|
+
USDT: 6,
|
|
104079
|
+
DAI: 18
|
|
104080
|
+
};
|
|
104081
|
+
|
|
104023
104082
|
// src/types/error.ts
|
|
104024
104083
|
var SDKErrorCode = /* @__PURE__ */ ((SDKErrorCode2) => {
|
|
104025
104084
|
SDKErrorCode2["NOT_INITIALIZED"] = "NOT_INITIALIZED";
|
|
@@ -104088,65 +104147,6 @@ var SignInStatus = /* @__PURE__ */ ((SignInStatus2) => {
|
|
|
104088
104147
|
return SignInStatus2;
|
|
104089
104148
|
})(SignInStatus || {});
|
|
104090
104149
|
|
|
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
104150
|
// src/core/services/wallet.ts
|
|
104151
104151
|
var ERC20_ABI = [
|
|
104152
104152
|
"function balanceOf(address owner) view returns (uint256)",
|
|
@@ -104172,7 +104172,7 @@ var WalletService = class {
|
|
|
104172
104172
|
this.walletAddress = null;
|
|
104173
104173
|
}
|
|
104174
104174
|
/**
|
|
104175
|
-
*
|
|
104175
|
+
* Password/PIN mismatch detection for decrypt errors.
|
|
104176
104176
|
*/
|
|
104177
104177
|
isInvalidPasswordError(error) {
|
|
104178
104178
|
if (!error) return false;
|
|
@@ -104191,9 +104191,8 @@ var WalletService = class {
|
|
|
104191
104191
|
return /^[0-9]{6}$/.test(pin);
|
|
104192
104192
|
}
|
|
104193
104193
|
/**
|
|
104194
|
-
* deviceSecret
|
|
104195
|
-
*
|
|
104196
|
-
* - 서버에는 절대 전달하지 않습니다.
|
|
104194
|
+
* deviceSecret: local-only secret for device recovery material.
|
|
104195
|
+
* This must never be sent to server.
|
|
104197
104196
|
*/
|
|
104198
104197
|
async getOrCreateDeviceSecret() {
|
|
104199
104198
|
const key = STORAGE_KEYS.deviceSecret(this.orgHost);
|
|
@@ -104203,19 +104202,20 @@ var WalletService = class {
|
|
|
104203
104202
|
await LocalForage.save(key, secret);
|
|
104204
104203
|
return secret;
|
|
104205
104204
|
}
|
|
104205
|
+
/**
|
|
104206
|
+
* PATCH APPLIED:
|
|
104207
|
+
* Always overwrite encryptedShare2_device when we have a fresh share2.
|
|
104208
|
+
* Keeping an old device share causes (share1 new + share2 old) => different derived wallet.
|
|
104209
|
+
*/
|
|
104206
104210
|
async ensureDeviceEncryptedShare2(share2Plain, firebaseId) {
|
|
104207
104211
|
const encryptedKey = STORAGE_KEYS.encryptedShare2Device(this.orgHost);
|
|
104208
|
-
const existing = await LocalForage.get(encryptedKey);
|
|
104209
|
-
if (existing) return;
|
|
104210
104212
|
const deviceSecret = await this.getOrCreateDeviceSecret();
|
|
104211
104213
|
const encrypted = Crypto.encryptShare(share2Plain, deviceSecret, firebaseId);
|
|
104212
104214
|
await LocalForage.save(encryptedKey, encrypted);
|
|
104213
104215
|
}
|
|
104214
104216
|
async getAddress() {
|
|
104215
104217
|
try {
|
|
104216
|
-
if (this.walletAddress)
|
|
104217
|
-
return this.walletAddress;
|
|
104218
|
-
}
|
|
104218
|
+
if (this.walletAddress) return this.walletAddress;
|
|
104219
104219
|
const savedAddress = await LocalForage.get(
|
|
104220
104220
|
STORAGE_KEYS.walletAddress(this.orgHost)
|
|
104221
104221
|
);
|
|
@@ -104246,7 +104246,6 @@ var WalletService = class {
|
|
|
104246
104246
|
const firebaseId = await LocalForage.get(
|
|
104247
104247
|
STORAGE_KEYS.firebaseId(this.orgHost)
|
|
104248
104248
|
);
|
|
104249
|
-
console.log("1. FirebaseId:", firebaseId);
|
|
104250
104249
|
if (!firebaseId) {
|
|
104251
104250
|
throw new SDKError("Not logged in", "AUTH_REQUIRED" /* AUTH_REQUIRED */);
|
|
104252
104251
|
}
|
|
@@ -104268,27 +104267,18 @@ var WalletService = class {
|
|
|
104268
104267
|
"WALLET_ALREADY_EXISTS" /* WALLET_ALREADY_EXISTS */
|
|
104269
104268
|
);
|
|
104270
104269
|
}
|
|
104271
|
-
console.log("2. Generating wallet...");
|
|
104272
104270
|
const mnemonic = (0, import_bip39.generateMnemonic)();
|
|
104273
104271
|
const seed = await (0, import_bip39.mnemonicToSeed)(mnemonic);
|
|
104274
104272
|
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
104273
|
const shares = await Secrets.split(wallet.privateKey, 3, 2);
|
|
104281
104274
|
const [share1, share2, share3] = shares;
|
|
104282
|
-
console.log("6. Encrypting shares...");
|
|
104283
104275
|
const encryptedShare2 = Crypto.encryptShare(share2, password, firebaseId);
|
|
104284
104276
|
const encryptedShare3 = Crypto.encryptShare(share3, password, firebaseId);
|
|
104285
|
-
console.log("8. Saving encryptedShare2 to LocalForage...");
|
|
104286
104277
|
await LocalForage.save(
|
|
104287
104278
|
STORAGE_KEYS.encryptedShare2(this.orgHost),
|
|
104288
104279
|
encryptedShare2
|
|
104289
104280
|
);
|
|
104290
104281
|
await this.ensureDeviceEncryptedShare2(share2, firebaseId);
|
|
104291
|
-
console.log("10. Creating wallet on server...");
|
|
104292
104282
|
await this.walletClient.createWallet({
|
|
104293
104283
|
address: wallet.address,
|
|
104294
104284
|
publicKey: wallet.signingKey.publicKey,
|
|
@@ -104302,7 +104292,6 @@ var WalletService = class {
|
|
|
104302
104292
|
);
|
|
104303
104293
|
return wallet.address;
|
|
104304
104294
|
} catch (error) {
|
|
104305
|
-
console.error("Error in create wallet:", error);
|
|
104306
104295
|
if (error instanceof SDKError) throw error;
|
|
104307
104296
|
throw new SDKError(
|
|
104308
104297
|
"Failed to create wallet",
|
|
@@ -104357,8 +104346,13 @@ var WalletService = class {
|
|
|
104357
104346
|
share2 = decryptShareOrThrow(encryptedShare2);
|
|
104358
104347
|
await LocalForage.save(STORAGE_KEYS.share2(this.orgHost), share2);
|
|
104359
104348
|
} else {
|
|
104360
|
-
const share3 = decryptShareOrThrow(
|
|
104361
|
-
|
|
104349
|
+
const share3 = decryptShareOrThrow(
|
|
104350
|
+
walletInfo.encryptedShare3
|
|
104351
|
+
);
|
|
104352
|
+
const privateKey2 = await Secrets.combine([
|
|
104353
|
+
walletInfo.share1,
|
|
104354
|
+
share3
|
|
104355
|
+
]);
|
|
104362
104356
|
const wallet2 = new import_ethers2.Wallet(privateKey2);
|
|
104363
104357
|
const newShares = await Secrets.split(wallet2.privateKey, 3, 2);
|
|
104364
104358
|
const [newShare1, newShare2, newShare3] = newShares;
|
|
@@ -104385,7 +104379,10 @@ var WalletService = class {
|
|
|
104385
104379
|
return wallet2.address;
|
|
104386
104380
|
}
|
|
104387
104381
|
}
|
|
104388
|
-
const privateKey = await Secrets.combine([
|
|
104382
|
+
const privateKey = await Secrets.combine([
|
|
104383
|
+
walletInfo.share1,
|
|
104384
|
+
share2
|
|
104385
|
+
]);
|
|
104389
104386
|
const wallet = new import_ethers2.Wallet(privateKey);
|
|
104390
104387
|
await this.ensureDeviceEncryptedShare2(share2, firebaseId);
|
|
104391
104388
|
this.walletAddress = wallet.address;
|
|
@@ -104398,7 +104395,6 @@ var WalletService = class {
|
|
|
104398
104395
|
} catch (error) {
|
|
104399
104396
|
this.walletAddress = null;
|
|
104400
104397
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104401
|
-
console.error("Error in retrieveWallet:", error);
|
|
104402
104398
|
if (error instanceof SDKError) throw error;
|
|
104403
104399
|
throw new SDKError(
|
|
104404
104400
|
"Failed to retrieve wallet",
|
|
@@ -104408,9 +104404,7 @@ var WalletService = class {
|
|
|
104408
104404
|
}
|
|
104409
104405
|
}
|
|
104410
104406
|
/**
|
|
104411
|
-
*
|
|
104412
|
-
* - 같은 디바이스에 남아있는 encryptedShare2_device를 이용
|
|
104413
|
-
* - 서버는 PATCH /v1/wallets/keys 로 share1 / encryptedShare3 만 업데이트
|
|
104407
|
+
* PIN reset (same private key/address) using encryptedShare2_device.
|
|
104414
104408
|
*/
|
|
104415
104409
|
async resetPin(newPassword) {
|
|
104416
104410
|
try {
|
|
@@ -104435,16 +104429,10 @@ var WalletService = class {
|
|
|
104435
104429
|
const encryptedDevice = await LocalForage.get(
|
|
104436
104430
|
STORAGE_KEYS.encryptedShare2Device(this.orgHost)
|
|
104437
104431
|
);
|
|
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
104432
|
const deviceSecret = await LocalForage.get(
|
|
104445
104433
|
STORAGE_KEYS.deviceSecret(this.orgHost)
|
|
104446
104434
|
);
|
|
104447
|
-
if (!deviceSecret) {
|
|
104435
|
+
if (!encryptedDevice || !deviceSecret) {
|
|
104448
104436
|
throw new SDKError(
|
|
104449
104437
|
"PIN reset is not available on this device",
|
|
104450
104438
|
"RECOVERY_NOT_AVAILABLE" /* RECOVERY_NOT_AVAILABLE */
|
|
@@ -104461,7 +104449,10 @@ var WalletService = class {
|
|
|
104461
104449
|
);
|
|
104462
104450
|
}
|
|
104463
104451
|
const walletInfo = await this.walletClient.getWallet();
|
|
104464
|
-
const privateKey = await Secrets.combine([
|
|
104452
|
+
const privateKey = await Secrets.combine([
|
|
104453
|
+
walletInfo.share1,
|
|
104454
|
+
share2
|
|
104455
|
+
]);
|
|
104465
104456
|
const wallet = new import_ethers2.Wallet(privateKey);
|
|
104466
104457
|
const newShares = await Secrets.split(wallet.privateKey, 3, 2);
|
|
104467
104458
|
const [newShare1, newShare2, newShare3] = newShares;
|
|
@@ -104477,15 +104468,7 @@ var WalletService = class {
|
|
|
104477
104468
|
STORAGE_KEYS.encryptedShare2(this.orgHost),
|
|
104478
104469
|
Crypto.encryptShare(newShare2, newPassword, firebaseId)
|
|
104479
104470
|
);
|
|
104480
|
-
|
|
104481
|
-
newShare2,
|
|
104482
|
-
deviceSecret,
|
|
104483
|
-
firebaseId
|
|
104484
|
-
);
|
|
104485
|
-
await LocalForage.save(
|
|
104486
|
-
STORAGE_KEYS.encryptedShare2Device(this.orgHost),
|
|
104487
|
-
newEncryptedDevice
|
|
104488
|
-
);
|
|
104471
|
+
await this.ensureDeviceEncryptedShare2(newShare2, firebaseId);
|
|
104489
104472
|
this.walletAddress = wallet.address;
|
|
104490
104473
|
await LocalForage.save(
|
|
104491
104474
|
STORAGE_KEYS.walletAddress(this.orgHost),
|
|
@@ -104494,7 +104477,6 @@ var WalletService = class {
|
|
|
104494
104477
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104495
104478
|
return wallet.address;
|
|
104496
104479
|
} catch (error) {
|
|
104497
|
-
console.error("Error in resetPin:", error);
|
|
104498
104480
|
if (error instanceof SDKError) throw error;
|
|
104499
104481
|
throw new SDKError(
|
|
104500
104482
|
"Failed to reset PIN",
|
|
@@ -104532,38 +104514,20 @@ var WalletService = class {
|
|
|
104532
104514
|
const rawBalance = await this.rpcClient.sendRpc({
|
|
104533
104515
|
chainId,
|
|
104534
104516
|
method: "eth_call" /* ETH_CALL */,
|
|
104535
|
-
params: [
|
|
104536
|
-
{
|
|
104537
|
-
to: tokenAddress,
|
|
104538
|
-
data
|
|
104539
|
-
},
|
|
104540
|
-
"latest"
|
|
104541
|
-
]
|
|
104517
|
+
params: [{ to: tokenAddress, data }, "latest"]
|
|
104542
104518
|
});
|
|
104543
104519
|
const decimalsData = erc20.encodeFunctionData("decimals", []);
|
|
104544
104520
|
const decimalsRes = await this.rpcClient.sendRpc({
|
|
104545
104521
|
chainId,
|
|
104546
104522
|
method: "eth_call" /* ETH_CALL */,
|
|
104547
|
-
params: [
|
|
104548
|
-
{
|
|
104549
|
-
to: tokenAddress,
|
|
104550
|
-
data: decimalsData
|
|
104551
|
-
},
|
|
104552
|
-
"latest"
|
|
104553
|
-
]
|
|
104523
|
+
params: [{ to: tokenAddress, data: decimalsData }, "latest"]
|
|
104554
104524
|
});
|
|
104555
104525
|
const decimals = parseInt(decimalsRes.result, 16);
|
|
104556
104526
|
const symbolData = erc20.encodeFunctionData("symbol", []);
|
|
104557
104527
|
const symbolRes = await this.rpcClient.sendRpc({
|
|
104558
104528
|
chainId,
|
|
104559
104529
|
method: "eth_call" /* ETH_CALL */,
|
|
104560
|
-
params: [
|
|
104561
|
-
{
|
|
104562
|
-
to: tokenAddress,
|
|
104563
|
-
data: symbolData
|
|
104564
|
-
},
|
|
104565
|
-
"latest"
|
|
104566
|
-
]
|
|
104530
|
+
params: [{ to: tokenAddress, data: symbolData }, "latest"]
|
|
104567
104531
|
});
|
|
104568
104532
|
const symbol = erc20.decodeFunctionResult("symbol", symbolRes.result)[0];
|
|
104569
104533
|
return {
|
|
@@ -104652,34 +104616,36 @@ var WalletService = class {
|
|
|
104652
104616
|
method: "eth_getTransactionCount" /* ETH_GET_TRANSACTION_COUNT */,
|
|
104653
104617
|
params: [address, "latest"]
|
|
104654
104618
|
});
|
|
104655
|
-
if (!nonce.result || nonce.result === "0x0")
|
|
104656
|
-
return void 0;
|
|
104657
|
-
}
|
|
104619
|
+
if (!nonce.result || nonce.result === "0x0") return void 0;
|
|
104658
104620
|
return {
|
|
104659
104621
|
hash: "",
|
|
104660
104622
|
status: "SUCCESS" /* SUCCESS */,
|
|
104661
104623
|
timestamp: Date.now(),
|
|
104662
104624
|
value: "0"
|
|
104663
104625
|
};
|
|
104664
|
-
} catch
|
|
104665
|
-
console.error("Failed to get latest transaction:", error);
|
|
104626
|
+
} catch {
|
|
104666
104627
|
return void 0;
|
|
104667
104628
|
}
|
|
104668
104629
|
}
|
|
104630
|
+
/**
|
|
104631
|
+
* PATCH APPLIED (critical):
|
|
104632
|
+
* - Never overwrite cached walletAddress with derived signer address.
|
|
104633
|
+
* - If server/cached address != derived address => throw WALLET_RECOVERY_FAILED.
|
|
104634
|
+
*/
|
|
104669
104635
|
async sendTransaction(params) {
|
|
104636
|
+
const toHexQuantity = (v5) => {
|
|
104637
|
+
if (v5 === void 0 || v5 === null) return "0x0";
|
|
104638
|
+
const s5 = String(v5).trim();
|
|
104639
|
+
if (!s5) return "0x0";
|
|
104640
|
+
if (s5.startsWith("0x") || s5.startsWith("0X")) return s5;
|
|
104641
|
+
try {
|
|
104642
|
+
const bi = BigInt(s5);
|
|
104643
|
+
return "0x" + bi.toString(16);
|
|
104644
|
+
} catch {
|
|
104645
|
+
return s5;
|
|
104646
|
+
}
|
|
104647
|
+
};
|
|
104670
104648
|
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
104649
|
const walletInfo = await this.walletClient.getWallet();
|
|
104684
104650
|
const share1 = walletInfo?.share1;
|
|
104685
104651
|
let share2 = await LocalForage.get(
|
|
@@ -104716,25 +104682,25 @@ var WalletService = class {
|
|
|
104716
104682
|
const privateKey = await Secrets.combine([share1, share2]);
|
|
104717
104683
|
const wallet = new import_ethers2.Wallet(privateKey);
|
|
104718
104684
|
const from = wallet.address;
|
|
104719
|
-
const
|
|
104720
|
-
|
|
104721
|
-
|
|
104722
|
-
|
|
104723
|
-
|
|
104724
|
-
|
|
104725
|
-
|
|
104726
|
-
|
|
104727
|
-
|
|
104685
|
+
const serverAddress = String(walletInfo?.address ?? "").trim();
|
|
104686
|
+
const cachedAddress = String(
|
|
104687
|
+
await LocalForage.get(
|
|
104688
|
+
STORAGE_KEYS.walletAddress(this.orgHost)
|
|
104689
|
+
) ?? ""
|
|
104690
|
+
).trim();
|
|
104691
|
+
const mismatch = (a5, b4) => a5 && b4 && a5.toLowerCase() !== b4.toLowerCase();
|
|
104692
|
+
if (mismatch(serverAddress, from) || mismatch(cachedAddress, from)) {
|
|
104693
|
+
throw new SDKError(
|
|
104694
|
+
`Wallet share mismatch detected. server=${serverAddress || "N/A"} cached=${cachedAddress || "N/A"} derived=${from}. Please re-enter PIN (retrieveWallet/resetPin) to refresh shares.`,
|
|
104695
|
+
"WALLET_RECOVERY_FAILED" /* WALLET_RECOVERY_FAILED */
|
|
104728
104696
|
);
|
|
104729
|
-
this.walletAddress = from;
|
|
104730
|
-
await LocalForage.save(STORAGE_KEYS.walletAddress(this.orgHost), from);
|
|
104731
104697
|
}
|
|
104732
104698
|
const nativeBal = await this.rpcClient.sendRpc({
|
|
104733
104699
|
chainId: params.chainId,
|
|
104734
104700
|
method: "eth_getBalance" /* ETH_GET_BALANCE */,
|
|
104735
104701
|
params: [from, "latest"]
|
|
104736
104702
|
});
|
|
104737
|
-
if (!nativeBal?.result || BigInt(nativeBal.result) ===
|
|
104703
|
+
if (!nativeBal?.result || BigInt(nativeBal.result) === 0n) {
|
|
104738
104704
|
throw new SDKError(
|
|
104739
104705
|
`Insufficient native balance for gas. sender=${from} balance=${nativeBal?.result ?? "0x0"}`,
|
|
104740
104706
|
"TRANSACTION_FAILED" /* TRANSACTION_FAILED */
|
|
@@ -104770,17 +104736,16 @@ var WalletService = class {
|
|
|
104770
104736
|
);
|
|
104771
104737
|
const buffered = Math.max(21e3, Math.ceil(est * 1.2));
|
|
104772
104738
|
gasLimit = "0x" + buffered.toString(16);
|
|
104773
|
-
} catch
|
|
104739
|
+
} catch {
|
|
104774
104740
|
const data = (params.data || "0x").toLowerCase();
|
|
104775
104741
|
const isApprove = data.startsWith("0x095ea7b3");
|
|
104776
104742
|
const fallback = isApprove ? 12e4 : data !== "0x" ? 8e5 : 21e3;
|
|
104777
104743
|
gasLimit = "0x" + fallback.toString(16);
|
|
104778
104744
|
}
|
|
104779
104745
|
}
|
|
104780
|
-
const value = params.value ?? "0";
|
|
104781
104746
|
const signedTx = await wallet.signTransaction({
|
|
104782
104747
|
to: params.to,
|
|
104783
|
-
value,
|
|
104748
|
+
value: params.value ?? "0",
|
|
104784
104749
|
data: params.data || "0x",
|
|
104785
104750
|
chainId: params.chainId,
|
|
104786
104751
|
nonce,
|
|
@@ -104791,12 +104756,10 @@ var WalletService = class {
|
|
|
104791
104756
|
const parsed = import_ethers2.Transaction.from(signedTx);
|
|
104792
104757
|
const derivedFrom = parsed?.from;
|
|
104793
104758
|
if (derivedFrom && String(derivedFrom).toLowerCase() !== from.toLowerCase()) {
|
|
104794
|
-
console.warn(
|
|
104795
|
-
|
|
104796
|
-
|
|
104797
|
-
|
|
104798
|
-
derivedFrom
|
|
104799
|
-
);
|
|
104759
|
+
console.warn("[WalletService] signedTx sender mismatch.", {
|
|
104760
|
+
walletFrom: from,
|
|
104761
|
+
txFrom: derivedFrom
|
|
104762
|
+
});
|
|
104800
104763
|
}
|
|
104801
104764
|
} catch {
|
|
104802
104765
|
}
|
|
@@ -104804,9 +104767,8 @@ var WalletService = class {
|
|
|
104804
104767
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104805
104768
|
return txHash;
|
|
104806
104769
|
} catch (error) {
|
|
104807
|
-
|
|
104808
|
-
|
|
104809
|
-
}
|
|
104770
|
+
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104771
|
+
if (error instanceof SDKError) throw error;
|
|
104810
104772
|
const msg = (() => {
|
|
104811
104773
|
try {
|
|
104812
104774
|
const anyErr = error;
|