@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.js
CHANGED
|
@@ -1893,26 +1893,6 @@ var AuthService = class {
|
|
|
1893
1893
|
import { Wallet, Interface, Transaction as EthersTx } from "ethers";
|
|
1894
1894
|
import { generateMnemonic, mnemonicToSeed } from "bip39";
|
|
1895
1895
|
|
|
1896
|
-
// src/utils/secrets.ts
|
|
1897
|
-
import { split, combine } from "shamir-secret-sharing";
|
|
1898
|
-
var Secrets = {
|
|
1899
|
-
async split(secret, total, threshold) {
|
|
1900
|
-
if (secret.startsWith("0x")) {
|
|
1901
|
-
secret = secret.substring(2);
|
|
1902
|
-
}
|
|
1903
|
-
const array = await split(
|
|
1904
|
-
new Uint8Array(Buffer.from(secret, "hex")),
|
|
1905
|
-
total,
|
|
1906
|
-
threshold
|
|
1907
|
-
);
|
|
1908
|
-
return array.map((item) => Buffer.from(item).toString("hex"));
|
|
1909
|
-
},
|
|
1910
|
-
async combine(shares) {
|
|
1911
|
-
const array = shares.map((item) => new Uint8Array(Buffer.from(item, "hex")));
|
|
1912
|
-
return `0x${Buffer.from(await combine(array)).toString("hex")}`;
|
|
1913
|
-
}
|
|
1914
|
-
};
|
|
1915
|
-
|
|
1916
1896
|
// node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/chunk-CcCWfKp1.js
|
|
1917
1897
|
var exports$22 = {};
|
|
1918
1898
|
var _dewExec$12 = false;
|
|
@@ -103928,6 +103908,26 @@ var webcrypto = exports11.webcrypto;
|
|
|
103928
103908
|
var getRandomValues = exports11.getRandomValues;
|
|
103929
103909
|
var randomUUID = exports11.randomUUID;
|
|
103930
103910
|
|
|
103911
|
+
// src/utils/secrets.ts
|
|
103912
|
+
import { split, combine } from "shamir-secret-sharing";
|
|
103913
|
+
var Secrets = {
|
|
103914
|
+
async split(secret, total, threshold) {
|
|
103915
|
+
if (secret.startsWith("0x")) {
|
|
103916
|
+
secret = secret.substring(2);
|
|
103917
|
+
}
|
|
103918
|
+
const array = await split(
|
|
103919
|
+
new Uint8Array(Buffer.from(secret, "hex")),
|
|
103920
|
+
total,
|
|
103921
|
+
threshold
|
|
103922
|
+
);
|
|
103923
|
+
return array.map((item) => Buffer.from(item).toString("hex"));
|
|
103924
|
+
},
|
|
103925
|
+
async combine(shares) {
|
|
103926
|
+
const array = shares.map((item) => new Uint8Array(Buffer.from(item, "hex")));
|
|
103927
|
+
return `0x${Buffer.from(await combine(array)).toString("hex")}`;
|
|
103928
|
+
}
|
|
103929
|
+
};
|
|
103930
|
+
|
|
103931
103931
|
// src/utils/crypto.ts
|
|
103932
103932
|
import * as ed from "@noble/ed25519";
|
|
103933
103933
|
function urlEncode(pemKey) {
|
|
@@ -103975,6 +103975,65 @@ var Crypto = {
|
|
|
103975
103975
|
}
|
|
103976
103976
|
};
|
|
103977
103977
|
|
|
103978
|
+
// src/utils/numbers.ts
|
|
103979
|
+
import { parseUnits, formatUnits } from "ethers";
|
|
103980
|
+
var TokenAmount = class {
|
|
103981
|
+
/**
|
|
103982
|
+
* Wei 단위의 값을 사용자가 읽을 수 있는 형태로 변환
|
|
103983
|
+
* @param value - Wei 단위의 값 (hex string 또는 decimal string)
|
|
103984
|
+
* @param decimals - 토큰의 소수점 자리수
|
|
103985
|
+
* @returns 변환된 문자열
|
|
103986
|
+
*/
|
|
103987
|
+
static fromWei(value, decimals) {
|
|
103988
|
+
try {
|
|
103989
|
+
return formatUnits(value, decimals);
|
|
103990
|
+
} catch (error) {
|
|
103991
|
+
console.error("Error converting from wei:", error);
|
|
103992
|
+
return "0.0";
|
|
103993
|
+
}
|
|
103994
|
+
}
|
|
103995
|
+
/**
|
|
103996
|
+
* 사용자 입력값을 Wei 단위로 변환
|
|
103997
|
+
* @param value - 사용자 입력값 (예: "1.5")
|
|
103998
|
+
* @param decimals - 토큰의 소수점 자리수
|
|
103999
|
+
* @returns Wei 단위의 값
|
|
104000
|
+
*/
|
|
104001
|
+
static toWei(value, decimals) {
|
|
104002
|
+
try {
|
|
104003
|
+
return parseUnits(value, decimals).toString();
|
|
104004
|
+
} catch (error) {
|
|
104005
|
+
console.error("Error converting to wei:", error);
|
|
104006
|
+
return "0";
|
|
104007
|
+
}
|
|
104008
|
+
}
|
|
104009
|
+
/**
|
|
104010
|
+
* 표시용 포맷으로 변환
|
|
104011
|
+
* @param value - Wei 단위의 값
|
|
104012
|
+
* @param decimals - 토큰의 소수점 자리수
|
|
104013
|
+
* @param maxDecimals - 최대 표시할 소수점 자리수 (기본값: 4)
|
|
104014
|
+
* @returns 포맷된 문자열
|
|
104015
|
+
*/
|
|
104016
|
+
static format(value, decimals, maxDecimals = 4) {
|
|
104017
|
+
const fullNumber = this.fromWei(value, decimals);
|
|
104018
|
+
const [beforeDecimal, afterDecimal = ""] = fullNumber.split(".");
|
|
104019
|
+
return `${beforeDecimal}.${afterDecimal.slice(0, maxDecimals)}`;
|
|
104020
|
+
}
|
|
104021
|
+
/**
|
|
104022
|
+
* 값이 유효한지 검증
|
|
104023
|
+
* @param value - 검증할 값
|
|
104024
|
+
* @returns 유효성 여부
|
|
104025
|
+
*/
|
|
104026
|
+
static isValid(value) {
|
|
104027
|
+
return /^\d*\.?\d*$/.test(value) && value !== "";
|
|
104028
|
+
}
|
|
104029
|
+
};
|
|
104030
|
+
var DECIMALS = {
|
|
104031
|
+
ETH: 18,
|
|
104032
|
+
USDC: 6,
|
|
104033
|
+
USDT: 6,
|
|
104034
|
+
DAI: 18
|
|
104035
|
+
};
|
|
104036
|
+
|
|
103978
104037
|
// src/types/error.ts
|
|
103979
104038
|
var SDKErrorCode = /* @__PURE__ */ ((SDKErrorCode2) => {
|
|
103980
104039
|
SDKErrorCode2["NOT_INITIALIZED"] = "NOT_INITIALIZED";
|
|
@@ -104043,65 +104102,6 @@ var SignInStatus = /* @__PURE__ */ ((SignInStatus2) => {
|
|
|
104043
104102
|
return SignInStatus2;
|
|
104044
104103
|
})(SignInStatus || {});
|
|
104045
104104
|
|
|
104046
|
-
// src/utils/numbers.ts
|
|
104047
|
-
import { parseUnits, formatUnits } from "ethers";
|
|
104048
|
-
var TokenAmount = class {
|
|
104049
|
-
/**
|
|
104050
|
-
* Wei 단위의 값을 사용자가 읽을 수 있는 형태로 변환
|
|
104051
|
-
* @param value - Wei 단위의 값 (hex string 또는 decimal string)
|
|
104052
|
-
* @param decimals - 토큰의 소수점 자리수
|
|
104053
|
-
* @returns 변환된 문자열
|
|
104054
|
-
*/
|
|
104055
|
-
static fromWei(value, decimals) {
|
|
104056
|
-
try {
|
|
104057
|
-
return formatUnits(value, decimals);
|
|
104058
|
-
} catch (error) {
|
|
104059
|
-
console.error("Error converting from wei:", error);
|
|
104060
|
-
return "0.0";
|
|
104061
|
-
}
|
|
104062
|
-
}
|
|
104063
|
-
/**
|
|
104064
|
-
* 사용자 입력값을 Wei 단위로 변환
|
|
104065
|
-
* @param value - 사용자 입력값 (예: "1.5")
|
|
104066
|
-
* @param decimals - 토큰의 소수점 자리수
|
|
104067
|
-
* @returns Wei 단위의 값
|
|
104068
|
-
*/
|
|
104069
|
-
static toWei(value, decimals) {
|
|
104070
|
-
try {
|
|
104071
|
-
return parseUnits(value, decimals).toString();
|
|
104072
|
-
} catch (error) {
|
|
104073
|
-
console.error("Error converting to wei:", error);
|
|
104074
|
-
return "0";
|
|
104075
|
-
}
|
|
104076
|
-
}
|
|
104077
|
-
/**
|
|
104078
|
-
* 표시용 포맷으로 변환
|
|
104079
|
-
* @param value - Wei 단위의 값
|
|
104080
|
-
* @param decimals - 토큰의 소수점 자리수
|
|
104081
|
-
* @param maxDecimals - 최대 표시할 소수점 자리수 (기본값: 4)
|
|
104082
|
-
* @returns 포맷된 문자열
|
|
104083
|
-
*/
|
|
104084
|
-
static format(value, decimals, maxDecimals = 4) {
|
|
104085
|
-
const fullNumber = this.fromWei(value, decimals);
|
|
104086
|
-
const [beforeDecimal, afterDecimal = ""] = fullNumber.split(".");
|
|
104087
|
-
return `${beforeDecimal}.${afterDecimal.slice(0, maxDecimals)}`;
|
|
104088
|
-
}
|
|
104089
|
-
/**
|
|
104090
|
-
* 값이 유효한지 검증
|
|
104091
|
-
* @param value - 검증할 값
|
|
104092
|
-
* @returns 유효성 여부
|
|
104093
|
-
*/
|
|
104094
|
-
static isValid(value) {
|
|
104095
|
-
return /^\d*\.?\d*$/.test(value) && value !== "";
|
|
104096
|
-
}
|
|
104097
|
-
};
|
|
104098
|
-
var DECIMALS = {
|
|
104099
|
-
ETH: 18,
|
|
104100
|
-
USDC: 6,
|
|
104101
|
-
USDT: 6,
|
|
104102
|
-
DAI: 18
|
|
104103
|
-
};
|
|
104104
|
-
|
|
104105
104105
|
// src/core/services/wallet.ts
|
|
104106
104106
|
var ERC20_ABI = [
|
|
104107
104107
|
"function balanceOf(address owner) view returns (uint256)",
|
|
@@ -104127,7 +104127,7 @@ var WalletService = class {
|
|
|
104127
104127
|
this.walletAddress = null;
|
|
104128
104128
|
}
|
|
104129
104129
|
/**
|
|
104130
|
-
*
|
|
104130
|
+
* Password/PIN mismatch detection for decrypt errors.
|
|
104131
104131
|
*/
|
|
104132
104132
|
isInvalidPasswordError(error) {
|
|
104133
104133
|
if (!error) return false;
|
|
@@ -104146,9 +104146,8 @@ var WalletService = class {
|
|
|
104146
104146
|
return /^[0-9]{6}$/.test(pin);
|
|
104147
104147
|
}
|
|
104148
104148
|
/**
|
|
104149
|
-
* deviceSecret
|
|
104150
|
-
*
|
|
104151
|
-
* - 서버에는 절대 전달하지 않습니다.
|
|
104149
|
+
* deviceSecret: local-only secret for device recovery material.
|
|
104150
|
+
* This must never be sent to server.
|
|
104152
104151
|
*/
|
|
104153
104152
|
async getOrCreateDeviceSecret() {
|
|
104154
104153
|
const key = STORAGE_KEYS.deviceSecret(this.orgHost);
|
|
@@ -104158,19 +104157,20 @@ var WalletService = class {
|
|
|
104158
104157
|
await LocalForage.save(key, secret);
|
|
104159
104158
|
return secret;
|
|
104160
104159
|
}
|
|
104160
|
+
/**
|
|
104161
|
+
* PATCH APPLIED:
|
|
104162
|
+
* Always overwrite encryptedShare2_device when we have a fresh share2.
|
|
104163
|
+
* Keeping an old device share causes (share1 new + share2 old) => different derived wallet.
|
|
104164
|
+
*/
|
|
104161
104165
|
async ensureDeviceEncryptedShare2(share2Plain, firebaseId) {
|
|
104162
104166
|
const encryptedKey = STORAGE_KEYS.encryptedShare2Device(this.orgHost);
|
|
104163
|
-
const existing = await LocalForage.get(encryptedKey);
|
|
104164
|
-
if (existing) return;
|
|
104165
104167
|
const deviceSecret = await this.getOrCreateDeviceSecret();
|
|
104166
104168
|
const encrypted = Crypto.encryptShare(share2Plain, deviceSecret, firebaseId);
|
|
104167
104169
|
await LocalForage.save(encryptedKey, encrypted);
|
|
104168
104170
|
}
|
|
104169
104171
|
async getAddress() {
|
|
104170
104172
|
try {
|
|
104171
|
-
if (this.walletAddress)
|
|
104172
|
-
return this.walletAddress;
|
|
104173
|
-
}
|
|
104173
|
+
if (this.walletAddress) return this.walletAddress;
|
|
104174
104174
|
const savedAddress = await LocalForage.get(
|
|
104175
104175
|
STORAGE_KEYS.walletAddress(this.orgHost)
|
|
104176
104176
|
);
|
|
@@ -104201,7 +104201,6 @@ var WalletService = class {
|
|
|
104201
104201
|
const firebaseId = await LocalForage.get(
|
|
104202
104202
|
STORAGE_KEYS.firebaseId(this.orgHost)
|
|
104203
104203
|
);
|
|
104204
|
-
console.log("1. FirebaseId:", firebaseId);
|
|
104205
104204
|
if (!firebaseId) {
|
|
104206
104205
|
throw new SDKError("Not logged in", "AUTH_REQUIRED" /* AUTH_REQUIRED */);
|
|
104207
104206
|
}
|
|
@@ -104223,27 +104222,18 @@ var WalletService = class {
|
|
|
104223
104222
|
"WALLET_ALREADY_EXISTS" /* WALLET_ALREADY_EXISTS */
|
|
104224
104223
|
);
|
|
104225
104224
|
}
|
|
104226
|
-
console.log("2. Generating wallet...");
|
|
104227
104225
|
const mnemonic = generateMnemonic();
|
|
104228
104226
|
const seed = await mnemonicToSeed(mnemonic);
|
|
104229
104227
|
const wallet = new Wallet(seed.slice(0, 32).toString("hex"));
|
|
104230
|
-
console.log("3. Wallet created:", {
|
|
104231
|
-
address: wallet.address,
|
|
104232
|
-
publicKey: wallet.signingKey.publicKey
|
|
104233
|
-
});
|
|
104234
|
-
console.log("4. Splitting private key...");
|
|
104235
104228
|
const shares = await Secrets.split(wallet.privateKey, 3, 2);
|
|
104236
104229
|
const [share1, share2, share3] = shares;
|
|
104237
|
-
console.log("6. Encrypting shares...");
|
|
104238
104230
|
const encryptedShare2 = Crypto.encryptShare(share2, password, firebaseId);
|
|
104239
104231
|
const encryptedShare3 = Crypto.encryptShare(share3, password, firebaseId);
|
|
104240
|
-
console.log("8. Saving encryptedShare2 to LocalForage...");
|
|
104241
104232
|
await LocalForage.save(
|
|
104242
104233
|
STORAGE_KEYS.encryptedShare2(this.orgHost),
|
|
104243
104234
|
encryptedShare2
|
|
104244
104235
|
);
|
|
104245
104236
|
await this.ensureDeviceEncryptedShare2(share2, firebaseId);
|
|
104246
|
-
console.log("10. Creating wallet on server...");
|
|
104247
104237
|
await this.walletClient.createWallet({
|
|
104248
104238
|
address: wallet.address,
|
|
104249
104239
|
publicKey: wallet.signingKey.publicKey,
|
|
@@ -104257,7 +104247,6 @@ var WalletService = class {
|
|
|
104257
104247
|
);
|
|
104258
104248
|
return wallet.address;
|
|
104259
104249
|
} catch (error) {
|
|
104260
|
-
console.error("Error in create wallet:", error);
|
|
104261
104250
|
if (error instanceof SDKError) throw error;
|
|
104262
104251
|
throw new SDKError(
|
|
104263
104252
|
"Failed to create wallet",
|
|
@@ -104312,8 +104301,13 @@ var WalletService = class {
|
|
|
104312
104301
|
share2 = decryptShareOrThrow(encryptedShare2);
|
|
104313
104302
|
await LocalForage.save(STORAGE_KEYS.share2(this.orgHost), share2);
|
|
104314
104303
|
} else {
|
|
104315
|
-
const share3 = decryptShareOrThrow(
|
|
104316
|
-
|
|
104304
|
+
const share3 = decryptShareOrThrow(
|
|
104305
|
+
walletInfo.encryptedShare3
|
|
104306
|
+
);
|
|
104307
|
+
const privateKey2 = await Secrets.combine([
|
|
104308
|
+
walletInfo.share1,
|
|
104309
|
+
share3
|
|
104310
|
+
]);
|
|
104317
104311
|
const wallet2 = new Wallet(privateKey2);
|
|
104318
104312
|
const newShares = await Secrets.split(wallet2.privateKey, 3, 2);
|
|
104319
104313
|
const [newShare1, newShare2, newShare3] = newShares;
|
|
@@ -104340,7 +104334,10 @@ var WalletService = class {
|
|
|
104340
104334
|
return wallet2.address;
|
|
104341
104335
|
}
|
|
104342
104336
|
}
|
|
104343
|
-
const privateKey = await Secrets.combine([
|
|
104337
|
+
const privateKey = await Secrets.combine([
|
|
104338
|
+
walletInfo.share1,
|
|
104339
|
+
share2
|
|
104340
|
+
]);
|
|
104344
104341
|
const wallet = new Wallet(privateKey);
|
|
104345
104342
|
await this.ensureDeviceEncryptedShare2(share2, firebaseId);
|
|
104346
104343
|
this.walletAddress = wallet.address;
|
|
@@ -104353,7 +104350,6 @@ var WalletService = class {
|
|
|
104353
104350
|
} catch (error) {
|
|
104354
104351
|
this.walletAddress = null;
|
|
104355
104352
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104356
|
-
console.error("Error in retrieveWallet:", error);
|
|
104357
104353
|
if (error instanceof SDKError) throw error;
|
|
104358
104354
|
throw new SDKError(
|
|
104359
104355
|
"Failed to retrieve wallet",
|
|
@@ -104363,9 +104359,7 @@ var WalletService = class {
|
|
|
104363
104359
|
}
|
|
104364
104360
|
}
|
|
104365
104361
|
/**
|
|
104366
|
-
*
|
|
104367
|
-
* - 같은 디바이스에 남아있는 encryptedShare2_device를 이용
|
|
104368
|
-
* - 서버는 PATCH /v1/wallets/keys 로 share1 / encryptedShare3 만 업데이트
|
|
104362
|
+
* PIN reset (same private key/address) using encryptedShare2_device.
|
|
104369
104363
|
*/
|
|
104370
104364
|
async resetPin(newPassword) {
|
|
104371
104365
|
try {
|
|
@@ -104390,16 +104384,10 @@ var WalletService = class {
|
|
|
104390
104384
|
const encryptedDevice = await LocalForage.get(
|
|
104391
104385
|
STORAGE_KEYS.encryptedShare2Device(this.orgHost)
|
|
104392
104386
|
);
|
|
104393
|
-
if (!encryptedDevice) {
|
|
104394
|
-
throw new SDKError(
|
|
104395
|
-
"PIN reset is not available on this device",
|
|
104396
|
-
"RECOVERY_NOT_AVAILABLE" /* RECOVERY_NOT_AVAILABLE */
|
|
104397
|
-
);
|
|
104398
|
-
}
|
|
104399
104387
|
const deviceSecret = await LocalForage.get(
|
|
104400
104388
|
STORAGE_KEYS.deviceSecret(this.orgHost)
|
|
104401
104389
|
);
|
|
104402
|
-
if (!deviceSecret) {
|
|
104390
|
+
if (!encryptedDevice || !deviceSecret) {
|
|
104403
104391
|
throw new SDKError(
|
|
104404
104392
|
"PIN reset is not available on this device",
|
|
104405
104393
|
"RECOVERY_NOT_AVAILABLE" /* RECOVERY_NOT_AVAILABLE */
|
|
@@ -104416,7 +104404,10 @@ var WalletService = class {
|
|
|
104416
104404
|
);
|
|
104417
104405
|
}
|
|
104418
104406
|
const walletInfo = await this.walletClient.getWallet();
|
|
104419
|
-
const privateKey = await Secrets.combine([
|
|
104407
|
+
const privateKey = await Secrets.combine([
|
|
104408
|
+
walletInfo.share1,
|
|
104409
|
+
share2
|
|
104410
|
+
]);
|
|
104420
104411
|
const wallet = new Wallet(privateKey);
|
|
104421
104412
|
const newShares = await Secrets.split(wallet.privateKey, 3, 2);
|
|
104422
104413
|
const [newShare1, newShare2, newShare3] = newShares;
|
|
@@ -104432,15 +104423,7 @@ var WalletService = class {
|
|
|
104432
104423
|
STORAGE_KEYS.encryptedShare2(this.orgHost),
|
|
104433
104424
|
Crypto.encryptShare(newShare2, newPassword, firebaseId)
|
|
104434
104425
|
);
|
|
104435
|
-
|
|
104436
|
-
newShare2,
|
|
104437
|
-
deviceSecret,
|
|
104438
|
-
firebaseId
|
|
104439
|
-
);
|
|
104440
|
-
await LocalForage.save(
|
|
104441
|
-
STORAGE_KEYS.encryptedShare2Device(this.orgHost),
|
|
104442
|
-
newEncryptedDevice
|
|
104443
|
-
);
|
|
104426
|
+
await this.ensureDeviceEncryptedShare2(newShare2, firebaseId);
|
|
104444
104427
|
this.walletAddress = wallet.address;
|
|
104445
104428
|
await LocalForage.save(
|
|
104446
104429
|
STORAGE_KEYS.walletAddress(this.orgHost),
|
|
@@ -104449,7 +104432,6 @@ var WalletService = class {
|
|
|
104449
104432
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104450
104433
|
return wallet.address;
|
|
104451
104434
|
} catch (error) {
|
|
104452
|
-
console.error("Error in resetPin:", error);
|
|
104453
104435
|
if (error instanceof SDKError) throw error;
|
|
104454
104436
|
throw new SDKError(
|
|
104455
104437
|
"Failed to reset PIN",
|
|
@@ -104487,38 +104469,20 @@ var WalletService = class {
|
|
|
104487
104469
|
const rawBalance = await this.rpcClient.sendRpc({
|
|
104488
104470
|
chainId,
|
|
104489
104471
|
method: "eth_call" /* ETH_CALL */,
|
|
104490
|
-
params: [
|
|
104491
|
-
{
|
|
104492
|
-
to: tokenAddress,
|
|
104493
|
-
data
|
|
104494
|
-
},
|
|
104495
|
-
"latest"
|
|
104496
|
-
]
|
|
104472
|
+
params: [{ to: tokenAddress, data }, "latest"]
|
|
104497
104473
|
});
|
|
104498
104474
|
const decimalsData = erc20.encodeFunctionData("decimals", []);
|
|
104499
104475
|
const decimalsRes = await this.rpcClient.sendRpc({
|
|
104500
104476
|
chainId,
|
|
104501
104477
|
method: "eth_call" /* ETH_CALL */,
|
|
104502
|
-
params: [
|
|
104503
|
-
{
|
|
104504
|
-
to: tokenAddress,
|
|
104505
|
-
data: decimalsData
|
|
104506
|
-
},
|
|
104507
|
-
"latest"
|
|
104508
|
-
]
|
|
104478
|
+
params: [{ to: tokenAddress, data: decimalsData }, "latest"]
|
|
104509
104479
|
});
|
|
104510
104480
|
const decimals = parseInt(decimalsRes.result, 16);
|
|
104511
104481
|
const symbolData = erc20.encodeFunctionData("symbol", []);
|
|
104512
104482
|
const symbolRes = await this.rpcClient.sendRpc({
|
|
104513
104483
|
chainId,
|
|
104514
104484
|
method: "eth_call" /* ETH_CALL */,
|
|
104515
|
-
params: [
|
|
104516
|
-
{
|
|
104517
|
-
to: tokenAddress,
|
|
104518
|
-
data: symbolData
|
|
104519
|
-
},
|
|
104520
|
-
"latest"
|
|
104521
|
-
]
|
|
104485
|
+
params: [{ to: tokenAddress, data: symbolData }, "latest"]
|
|
104522
104486
|
});
|
|
104523
104487
|
const symbol = erc20.decodeFunctionResult("symbol", symbolRes.result)[0];
|
|
104524
104488
|
return {
|
|
@@ -104607,34 +104571,36 @@ var WalletService = class {
|
|
|
104607
104571
|
method: "eth_getTransactionCount" /* ETH_GET_TRANSACTION_COUNT */,
|
|
104608
104572
|
params: [address, "latest"]
|
|
104609
104573
|
});
|
|
104610
|
-
if (!nonce.result || nonce.result === "0x0")
|
|
104611
|
-
return void 0;
|
|
104612
|
-
}
|
|
104574
|
+
if (!nonce.result || nonce.result === "0x0") return void 0;
|
|
104613
104575
|
return {
|
|
104614
104576
|
hash: "",
|
|
104615
104577
|
status: "SUCCESS" /* SUCCESS */,
|
|
104616
104578
|
timestamp: Date.now(),
|
|
104617
104579
|
value: "0"
|
|
104618
104580
|
};
|
|
104619
|
-
} catch
|
|
104620
|
-
console.error("Failed to get latest transaction:", error);
|
|
104581
|
+
} catch {
|
|
104621
104582
|
return void 0;
|
|
104622
104583
|
}
|
|
104623
104584
|
}
|
|
104585
|
+
/**
|
|
104586
|
+
* PATCH APPLIED (critical):
|
|
104587
|
+
* - Never overwrite cached walletAddress with derived signer address.
|
|
104588
|
+
* - If server/cached address != derived address => throw WALLET_RECOVERY_FAILED.
|
|
104589
|
+
*/
|
|
104624
104590
|
async sendTransaction(params) {
|
|
104591
|
+
const toHexQuantity = (v5) => {
|
|
104592
|
+
if (v5 === void 0 || v5 === null) return "0x0";
|
|
104593
|
+
const s5 = String(v5).trim();
|
|
104594
|
+
if (!s5) return "0x0";
|
|
104595
|
+
if (s5.startsWith("0x") || s5.startsWith("0X")) return s5;
|
|
104596
|
+
try {
|
|
104597
|
+
const bi = BigInt(s5);
|
|
104598
|
+
return "0x" + bi.toString(16);
|
|
104599
|
+
} catch {
|
|
104600
|
+
return s5;
|
|
104601
|
+
}
|
|
104602
|
+
};
|
|
104625
104603
|
try {
|
|
104626
|
-
const toHexQuantity = (v5) => {
|
|
104627
|
-
if (v5 === void 0 || v5 === null) return "0x0";
|
|
104628
|
-
const s5 = String(v5).trim();
|
|
104629
|
-
if (!s5) return "0x0";
|
|
104630
|
-
if (s5.startsWith("0x") || s5.startsWith("0X")) return s5;
|
|
104631
|
-
try {
|
|
104632
|
-
const bi = BigInt(s5);
|
|
104633
|
-
return "0x" + bi.toString(16);
|
|
104634
|
-
} catch {
|
|
104635
|
-
return s5;
|
|
104636
|
-
}
|
|
104637
|
-
};
|
|
104638
104604
|
const walletInfo = await this.walletClient.getWallet();
|
|
104639
104605
|
const share1 = walletInfo?.share1;
|
|
104640
104606
|
let share2 = await LocalForage.get(
|
|
@@ -104671,25 +104637,25 @@ var WalletService = class {
|
|
|
104671
104637
|
const privateKey = await Secrets.combine([share1, share2]);
|
|
104672
104638
|
const wallet = new Wallet(privateKey);
|
|
104673
104639
|
const from = wallet.address;
|
|
104674
|
-
const
|
|
104675
|
-
|
|
104676
|
-
|
|
104677
|
-
|
|
104678
|
-
|
|
104679
|
-
|
|
104680
|
-
|
|
104681
|
-
|
|
104682
|
-
|
|
104640
|
+
const serverAddress = String(walletInfo?.address ?? "").trim();
|
|
104641
|
+
const cachedAddress = String(
|
|
104642
|
+
await LocalForage.get(
|
|
104643
|
+
STORAGE_KEYS.walletAddress(this.orgHost)
|
|
104644
|
+
) ?? ""
|
|
104645
|
+
).trim();
|
|
104646
|
+
const mismatch = (a5, b4) => a5 && b4 && a5.toLowerCase() !== b4.toLowerCase();
|
|
104647
|
+
if (mismatch(serverAddress, from) || mismatch(cachedAddress, from)) {
|
|
104648
|
+
throw new SDKError(
|
|
104649
|
+
`Wallet share mismatch detected. server=${serverAddress || "N/A"} cached=${cachedAddress || "N/A"} derived=${from}. Please re-enter PIN (retrieveWallet/resetPin) to refresh shares.`,
|
|
104650
|
+
"WALLET_RECOVERY_FAILED" /* WALLET_RECOVERY_FAILED */
|
|
104683
104651
|
);
|
|
104684
|
-
this.walletAddress = from;
|
|
104685
|
-
await LocalForage.save(STORAGE_KEYS.walletAddress(this.orgHost), from);
|
|
104686
104652
|
}
|
|
104687
104653
|
const nativeBal = await this.rpcClient.sendRpc({
|
|
104688
104654
|
chainId: params.chainId,
|
|
104689
104655
|
method: "eth_getBalance" /* ETH_GET_BALANCE */,
|
|
104690
104656
|
params: [from, "latest"]
|
|
104691
104657
|
});
|
|
104692
|
-
if (!nativeBal?.result || BigInt(nativeBal.result) ===
|
|
104658
|
+
if (!nativeBal?.result || BigInt(nativeBal.result) === 0n) {
|
|
104693
104659
|
throw new SDKError(
|
|
104694
104660
|
`Insufficient native balance for gas. sender=${from} balance=${nativeBal?.result ?? "0x0"}`,
|
|
104695
104661
|
"TRANSACTION_FAILED" /* TRANSACTION_FAILED */
|
|
@@ -104725,17 +104691,16 @@ var WalletService = class {
|
|
|
104725
104691
|
);
|
|
104726
104692
|
const buffered = Math.max(21e3, Math.ceil(est * 1.2));
|
|
104727
104693
|
gasLimit = "0x" + buffered.toString(16);
|
|
104728
|
-
} catch
|
|
104694
|
+
} catch {
|
|
104729
104695
|
const data = (params.data || "0x").toLowerCase();
|
|
104730
104696
|
const isApprove = data.startsWith("0x095ea7b3");
|
|
104731
104697
|
const fallback = isApprove ? 12e4 : data !== "0x" ? 8e5 : 21e3;
|
|
104732
104698
|
gasLimit = "0x" + fallback.toString(16);
|
|
104733
104699
|
}
|
|
104734
104700
|
}
|
|
104735
|
-
const value = params.value ?? "0";
|
|
104736
104701
|
const signedTx = await wallet.signTransaction({
|
|
104737
104702
|
to: params.to,
|
|
104738
|
-
value,
|
|
104703
|
+
value: params.value ?? "0",
|
|
104739
104704
|
data: params.data || "0x",
|
|
104740
104705
|
chainId: params.chainId,
|
|
104741
104706
|
nonce,
|
|
@@ -104746,12 +104711,10 @@ var WalletService = class {
|
|
|
104746
104711
|
const parsed = EthersTx.from(signedTx);
|
|
104747
104712
|
const derivedFrom = parsed?.from;
|
|
104748
104713
|
if (derivedFrom && String(derivedFrom).toLowerCase() !== from.toLowerCase()) {
|
|
104749
|
-
console.warn(
|
|
104750
|
-
|
|
104751
|
-
|
|
104752
|
-
|
|
104753
|
-
derivedFrom
|
|
104754
|
-
);
|
|
104714
|
+
console.warn("[WalletService] signedTx sender mismatch.", {
|
|
104715
|
+
walletFrom: from,
|
|
104716
|
+
txFrom: derivedFrom
|
|
104717
|
+
});
|
|
104755
104718
|
}
|
|
104756
104719
|
} catch {
|
|
104757
104720
|
}
|
|
@@ -104759,9 +104722,8 @@ var WalletService = class {
|
|
|
104759
104722
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104760
104723
|
return txHash;
|
|
104761
104724
|
} catch (error) {
|
|
104762
|
-
|
|
104763
|
-
|
|
104764
|
-
}
|
|
104725
|
+
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104726
|
+
if (error instanceof SDKError) throw error;
|
|
104765
104727
|
const msg = (() => {
|
|
104766
104728
|
try {
|
|
104767
104729
|
const anyErr = error;
|