@kingdomchain/wallet-client 0.4.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -130
- package/dist/index.d.ts +116 -11
- package/dist/index.js +273 -3
- package/dist/index.js.map +1 -1
- package/package.json +77 -77
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { toHex, fromHex, toBase64, fromBase64 } from '@cosmjs/encoding';
|
|
|
2
2
|
import { sha256 } from '@noble/hashes/sha256';
|
|
3
3
|
import * as ed from '@noble/ed25519';
|
|
4
4
|
import { Registry, DirectSecp256k1Wallet, DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
|
|
5
|
-
import { defaultRegistryTypes, SigningStargateClient } from '@cosmjs/stargate';
|
|
5
|
+
import { defaultRegistryTypes, SigningStargateClient, coins } from '@cosmjs/stargate';
|
|
6
6
|
import { BinaryWriter, BinaryReader } from '@bufbuild/protobuf/wire';
|
|
7
7
|
import SignClient from '@walletconnect/sign-client';
|
|
8
8
|
import { Bip39, EnglishMnemonic, Slip10, Slip10Curve, stringToPath } from '@cosmjs/crypto';
|
|
@@ -711,6 +711,61 @@ function fromTimestamp(t) {
|
|
|
711
711
|
millis += (t.nanos || 0) / 1e6;
|
|
712
712
|
return new globalThis.Date(millis);
|
|
713
713
|
}
|
|
714
|
+
function createBaseMsgClaimReward() {
|
|
715
|
+
return { claimer: "", day_id: 0n };
|
|
716
|
+
}
|
|
717
|
+
var MsgClaimReward = {
|
|
718
|
+
encode(message, writer = new BinaryWriter()) {
|
|
719
|
+
if (message.claimer !== "") {
|
|
720
|
+
writer.uint32(10).string(message.claimer);
|
|
721
|
+
}
|
|
722
|
+
if (message.day_id !== 0n) {
|
|
723
|
+
if (BigInt.asUintN(64, message.day_id) !== message.day_id) {
|
|
724
|
+
throw new globalThis.Error("value provided for field message.day_id of type uint64 too large");
|
|
725
|
+
}
|
|
726
|
+
writer.uint32(16).uint64(message.day_id);
|
|
727
|
+
}
|
|
728
|
+
return writer;
|
|
729
|
+
},
|
|
730
|
+
decode(input, length) {
|
|
731
|
+
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
732
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
733
|
+
const message = createBaseMsgClaimReward();
|
|
734
|
+
while (reader.pos < end) {
|
|
735
|
+
const tag = reader.uint32();
|
|
736
|
+
switch (tag >>> 3) {
|
|
737
|
+
case 1: {
|
|
738
|
+
if (tag !== 10) {
|
|
739
|
+
break;
|
|
740
|
+
}
|
|
741
|
+
message.claimer = reader.string();
|
|
742
|
+
continue;
|
|
743
|
+
}
|
|
744
|
+
case 2: {
|
|
745
|
+
if (tag !== 16) {
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
message.day_id = reader.uint64();
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
753
|
+
break;
|
|
754
|
+
}
|
|
755
|
+
reader.skip(tag & 7);
|
|
756
|
+
}
|
|
757
|
+
return message;
|
|
758
|
+
},
|
|
759
|
+
create(base) {
|
|
760
|
+
return MsgClaimReward.fromPartial(base ?? {});
|
|
761
|
+
},
|
|
762
|
+
fromPartial(object) {
|
|
763
|
+
const message = createBaseMsgClaimReward();
|
|
764
|
+
message.claimer = object.claimer ?? "";
|
|
765
|
+
message.day_id = object.day_id !== void 0 && object.day_id !== null ? BigInt(object.day_id) : 0n;
|
|
766
|
+
return message;
|
|
767
|
+
}
|
|
768
|
+
};
|
|
714
769
|
function createBaseMsgRegisterProvider() {
|
|
715
770
|
return {
|
|
716
771
|
authority: "",
|
|
@@ -1502,8 +1557,16 @@ var CITIZEN_MSG_TYPES = [
|
|
|
1502
1557
|
["/isatheword.kingdomchain.citizen.v1.MsgFinalizeRecovery", wrapMsgFns(MsgFinalizeRecovery)],
|
|
1503
1558
|
["/isatheword.kingdomchain.citizen.v1.MsgCancelRecovery", wrapMsgFns(MsgCancelRecovery)]
|
|
1504
1559
|
];
|
|
1560
|
+
var CITIZEN_REWARDS_MSG_TYPES = [
|
|
1561
|
+
["/isatheword.kingdomchain.citizenrewards.v1.MsgClaimReward", wrapMsgFns(MsgClaimReward)]
|
|
1562
|
+
];
|
|
1505
1563
|
function createKingdomChainRegistry() {
|
|
1506
|
-
return new Registry([
|
|
1564
|
+
return new Registry([
|
|
1565
|
+
...defaultRegistryTypes,
|
|
1566
|
+
...COMPLIANCE_MSG_TYPES,
|
|
1567
|
+
...CITIZEN_MSG_TYPES,
|
|
1568
|
+
...CITIZEN_REWARDS_MSG_TYPES
|
|
1569
|
+
]);
|
|
1507
1570
|
}
|
|
1508
1571
|
|
|
1509
1572
|
// src/chainConstants.ts
|
|
@@ -3115,6 +3178,213 @@ async function signCitizenshipAttestation(params) {
|
|
|
3115
3178
|
return { signature, input };
|
|
3116
3179
|
}
|
|
3117
3180
|
|
|
3118
|
-
|
|
3181
|
+
// src/amount.ts
|
|
3182
|
+
function parseKdrToUkdr(amountKdr) {
|
|
3183
|
+
const trimmed = amountKdr.trim();
|
|
3184
|
+
if (!trimmed) {
|
|
3185
|
+
throw new Error("Amount is required");
|
|
3186
|
+
}
|
|
3187
|
+
if (!/^\d+(\.\d+)?$/.test(trimmed)) {
|
|
3188
|
+
throw new Error("Amount must be a positive number");
|
|
3189
|
+
}
|
|
3190
|
+
const [whole, frac = ""] = trimmed.split(".");
|
|
3191
|
+
if (frac.length > UKDR_DECIMALS) {
|
|
3192
|
+
throw new Error(`Amount supports at most ${UKDR_DECIMALS} decimal places`);
|
|
3193
|
+
}
|
|
3194
|
+
const paddedFrac = frac.padEnd(UKDR_DECIMALS, "0");
|
|
3195
|
+
const ukdr = BigInt(whole + paddedFrac);
|
|
3196
|
+
if (ukdr <= 0n) {
|
|
3197
|
+
throw new Error("Amount must be greater than zero");
|
|
3198
|
+
}
|
|
3199
|
+
return ukdr.toString();
|
|
3200
|
+
}
|
|
3201
|
+
function formatUkdrAsKdr(amountUkdr) {
|
|
3202
|
+
const raw = typeof amountUkdr === "bigint" ? amountUkdr : BigInt(amountUkdr || "0");
|
|
3203
|
+
const negative = raw < 0n;
|
|
3204
|
+
const abs = negative ? -raw : raw;
|
|
3205
|
+
const whole = abs / 1000000n;
|
|
3206
|
+
const frac = abs % 1000000n;
|
|
3207
|
+
let fracStr = frac.toString().padStart(UKDR_DECIMALS, "0").replace(/0+$/, "");
|
|
3208
|
+
const formatted = fracStr ? `${whole}.${fracStr}` : whole.toString();
|
|
3209
|
+
return negative ? `-${formatted}` : formatted;
|
|
3210
|
+
}
|
|
3211
|
+
function ukdrCoin(amountUkdr) {
|
|
3212
|
+
return {
|
|
3213
|
+
denom: UKDR_MINIMAL_DENOM,
|
|
3214
|
+
amount: typeof amountUkdr === "bigint" ? amountUkdr.toString() : amountUkdr
|
|
3215
|
+
};
|
|
3216
|
+
}
|
|
3217
|
+
|
|
3218
|
+
// src/restQuery.ts
|
|
3219
|
+
var RestQueryError = class extends Error {
|
|
3220
|
+
constructor(message, status, cause) {
|
|
3221
|
+
super(message, { cause });
|
|
3222
|
+
this.status = status;
|
|
3223
|
+
this.name = "RestQueryError";
|
|
3224
|
+
}
|
|
3225
|
+
status;
|
|
3226
|
+
};
|
|
3227
|
+
async function restGet(restUrl, path) {
|
|
3228
|
+
const base = restUrl.replace(/\/$/, "");
|
|
3229
|
+
const res = await fetch(`${base}${path}`);
|
|
3230
|
+
if (!res.ok) {
|
|
3231
|
+
const body = await res.text().catch(() => "");
|
|
3232
|
+
throw new RestQueryError(
|
|
3233
|
+
body ? `LCD request failed (${res.status}): ${body}` : `LCD request failed (${res.status})`,
|
|
3234
|
+
res.status
|
|
3235
|
+
);
|
|
3236
|
+
}
|
|
3237
|
+
return await res.json();
|
|
3238
|
+
}
|
|
3239
|
+
async function fetchUkdrBalance(restUrl, address) {
|
|
3240
|
+
const data = await restGet(
|
|
3241
|
+
restUrl,
|
|
3242
|
+
`/cosmos/bank/v1beta1/balances/${encodeURIComponent(address)}`
|
|
3243
|
+
);
|
|
3244
|
+
const coin = data.balances.find((b) => b.denom === UKDR_MINIMAL_DENOM);
|
|
3245
|
+
return coin?.amount ?? "0";
|
|
3246
|
+
}
|
|
3247
|
+
async function fetchUnclaimedFinalizedRewards(restUrl, address) {
|
|
3248
|
+
const data = await restGet(
|
|
3249
|
+
restUrl,
|
|
3250
|
+
`/isatheword/kingdomchain/citizenrewards/v1/unclaimed_finalized_rewards/${encodeURIComponent(address)}`
|
|
3251
|
+
);
|
|
3252
|
+
return data.rewards ?? [];
|
|
3253
|
+
}
|
|
3254
|
+
async function fetchFeeGrantGranter(restUrl, grantee) {
|
|
3255
|
+
try {
|
|
3256
|
+
const data = await restGet(
|
|
3257
|
+
restUrl,
|
|
3258
|
+
`/cosmos/feegrant/v1beta1/allowances/${encodeURIComponent(grantee)}`
|
|
3259
|
+
);
|
|
3260
|
+
const first = data.allowances?.[0];
|
|
3261
|
+
return first?.granter?.trim() || null;
|
|
3262
|
+
} catch (err) {
|
|
3263
|
+
if (err instanceof RestQueryError && err.status === 404) {
|
|
3264
|
+
return null;
|
|
3265
|
+
}
|
|
3266
|
+
throw err;
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
var CitizenTxError = class extends Error {
|
|
3270
|
+
constructor(message, code, cause) {
|
|
3271
|
+
super(message, { cause });
|
|
3272
|
+
this.code = code;
|
|
3273
|
+
this.name = "CitizenTxError";
|
|
3274
|
+
}
|
|
3275
|
+
code;
|
|
3276
|
+
};
|
|
3277
|
+
var DEFAULT_GAS = "200000";
|
|
3278
|
+
var DEFAULT_FEE_UKDR = "5000";
|
|
3279
|
+
function buildSendUkdrMsg(fromAddress, toAddress, amountKdr) {
|
|
3280
|
+
if (!fromAddress.trim() || !toAddress.trim()) {
|
|
3281
|
+
throw new CitizenTxError("Sender and recipient are required", "INVALID_INPUT");
|
|
3282
|
+
}
|
|
3283
|
+
const amountUkdr = parseKdrToUkdr(amountKdr);
|
|
3284
|
+
return {
|
|
3285
|
+
typeUrl: "/cosmos.bank.v1beta1.MsgSend",
|
|
3286
|
+
value: {
|
|
3287
|
+
fromAddress,
|
|
3288
|
+
toAddress,
|
|
3289
|
+
amount: [ukdrCoin(amountUkdr)]
|
|
3290
|
+
}
|
|
3291
|
+
};
|
|
3292
|
+
}
|
|
3293
|
+
function buildClaimRewardMsg(claimer, dayId) {
|
|
3294
|
+
if (!claimer.trim()) {
|
|
3295
|
+
throw new CitizenTxError("Claimer address is required", "INVALID_INPUT");
|
|
3296
|
+
}
|
|
3297
|
+
const day = typeof dayId === "bigint" ? dayId : BigInt(dayId);
|
|
3298
|
+
if (day <= 0n) {
|
|
3299
|
+
throw new CitizenTxError("Reward day is required", "INVALID_INPUT");
|
|
3300
|
+
}
|
|
3301
|
+
return {
|
|
3302
|
+
typeUrl: "/isatheword.kingdomchain.citizenrewards.v1.MsgClaimReward",
|
|
3303
|
+
value: MsgClaimReward.fromPartial({
|
|
3304
|
+
claimer,
|
|
3305
|
+
day_id: day
|
|
3306
|
+
})
|
|
3307
|
+
};
|
|
3308
|
+
}
|
|
3309
|
+
function defaultUkdrTxFee(feeUkdr = DEFAULT_FEE_UKDR, feeGranter) {
|
|
3310
|
+
return {
|
|
3311
|
+
amount: coins(feeUkdr, UKDR_MINIMAL_DENOM),
|
|
3312
|
+
gas: DEFAULT_GAS,
|
|
3313
|
+
...feeGranter ? { granter: feeGranter } : {}
|
|
3314
|
+
};
|
|
3315
|
+
}
|
|
3316
|
+
function classifyBroadcastFailure(rawLog, code) {
|
|
3317
|
+
const log = rawLog.toLowerCase();
|
|
3318
|
+
if (log.includes("insufficient funds") || log.includes("insufficient fee")) {
|
|
3319
|
+
return log.includes("fee") ? "INSUFFICIENT_FEE" : "INSUFFICIENT_BALANCE";
|
|
3320
|
+
}
|
|
3321
|
+
if (log.includes("account sequence mismatch") || log.includes("wrong sequence")) {
|
|
3322
|
+
return "SEQUENCE_MISMATCH";
|
|
3323
|
+
}
|
|
3324
|
+
if (code !== 0) {
|
|
3325
|
+
return "TX_FAILED";
|
|
3326
|
+
}
|
|
3327
|
+
return "TX_FAILED";
|
|
3328
|
+
}
|
|
3329
|
+
function citizenTxErrorMessage(code) {
|
|
3330
|
+
switch (code) {
|
|
3331
|
+
case "INSUFFICIENT_FEE":
|
|
3332
|
+
return "This transaction needs a little more KDR for network fees. If you have not claimed yet, ask support to enable sponsored claim fees.";
|
|
3333
|
+
case "INSUFFICIENT_BALANCE":
|
|
3334
|
+
return "You do not have enough KDR for this transfer.";
|
|
3335
|
+
case "SEQUENCE_MISMATCH":
|
|
3336
|
+
return "Your wallet is out of sync. Refresh the page and try again.";
|
|
3337
|
+
case "TIMEOUT":
|
|
3338
|
+
return "The network is taking longer than usual. Your transaction may still confirm \u2014 check again in a moment.";
|
|
3339
|
+
case "INVALID_INPUT":
|
|
3340
|
+
return "Please check the amount and address and try again.";
|
|
3341
|
+
case "TX_FAILED":
|
|
3342
|
+
default:
|
|
3343
|
+
return "The transaction could not be completed. Please try again.";
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
async function broadcastAndConfirmTx(client, signerAddress, messages, fee, memo = "", options = {}) {
|
|
3347
|
+
const pollIntervalMs = options.pollIntervalMs ?? 1500;
|
|
3348
|
+
const timeoutMs = options.timeoutMs ?? 9e4;
|
|
3349
|
+
let deliverTx;
|
|
3350
|
+
try {
|
|
3351
|
+
deliverTx = await client.signAndBroadcast(signerAddress, messages, fee, memo);
|
|
3352
|
+
} catch (err) {
|
|
3353
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3354
|
+
if (message.toLowerCase().includes("insufficient")) {
|
|
3355
|
+
throw new CitizenTxError(citizenTxErrorMessage("INSUFFICIENT_FEE"), "INSUFFICIENT_FEE", err);
|
|
3356
|
+
}
|
|
3357
|
+
throw new CitizenTxError(citizenTxErrorMessage("TX_FAILED"), "TX_FAILED", err);
|
|
3358
|
+
}
|
|
3359
|
+
if (deliverTx.code !== 0) {
|
|
3360
|
+
const code = classifyBroadcastFailure(deliverTx.rawLog ?? "", deliverTx.code);
|
|
3361
|
+
throw new CitizenTxError(citizenTxErrorMessage(code), code);
|
|
3362
|
+
}
|
|
3363
|
+
const hash = deliverTx.transactionHash;
|
|
3364
|
+
const deadline = Date.now() + timeoutMs;
|
|
3365
|
+
while (Date.now() < deadline) {
|
|
3366
|
+
const indexed = await client.getTx(hash);
|
|
3367
|
+
if (indexed) {
|
|
3368
|
+
if (indexed.code !== 0) {
|
|
3369
|
+
const code = classifyBroadcastFailure(indexed.rawLog ?? "", indexed.code);
|
|
3370
|
+
throw new CitizenTxError(citizenTxErrorMessage(code), code);
|
|
3371
|
+
}
|
|
3372
|
+
return {
|
|
3373
|
+
hash,
|
|
3374
|
+
height: indexed.height,
|
|
3375
|
+
code: indexed.code,
|
|
3376
|
+
rawLog: indexed.rawLog ?? "",
|
|
3377
|
+
deliverTx: indexed
|
|
3378
|
+
};
|
|
3379
|
+
}
|
|
3380
|
+
await sleep(pollIntervalMs);
|
|
3381
|
+
}
|
|
3382
|
+
throw new CitizenTxError(citizenTxErrorMessage("TIMEOUT"), "TIMEOUT");
|
|
3383
|
+
}
|
|
3384
|
+
function sleep(ms) {
|
|
3385
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3386
|
+
}
|
|
3387
|
+
|
|
3388
|
+
export { ATTESTATION_TYPE_CITIZENSHIP_APPLICATION, ATTESTATION_TYPE_RECOVERY, ApplicationStatus, BECH32_PREFIX, CHAIN_COIN_TYPE, CitizenTxError, DEFAULT_CHAIN_ID, DEFAULT_REST_URL, DEFAULT_RPC_URL, EMBEDDED_WALLET_KDF_PBKDF2, EMBEDDED_WALLET_KDF_PIN, EMBEDDED_WALLET_KDF_PRF, EMBEDDED_WALLET_KEY_DIRECT_ENTROPY, EMBEDDED_WALLET_KEY_HD_DERIVED, EMBEDDED_WALLET_PASSCODE_MAX_LENGTH, EMBEDDED_WALLET_PASSCODE_MIN_LENGTH, EMBEDDED_WALLET_PASSKEY_PBKDF2_ITERATIONS, EMBEDDED_WALLET_PIN_PBKDF2_ITERATIONS, EMBEDDED_WALLET_RECOVERY_PHRASE_DIRECT_ENTROPY_WARNING, EMBEDDED_WALLET_RECOVERY_PHRASE_GENERAL_WARNING, EMBEDDED_WALLET_VAULT_VERSION, EmbeddedWalletBackupRequiredError, EmbeddedWalletDecryptError, EmbeddedWalletLockoutError, EmbeddedWalletVaultError, EmbeddedWalletWeakPasscodeError, InvalidChainConfigError, MsgClaimReward, MsgSubmitApplication, MsgSubmitRecoveryAttestation, PASSCODE_LOCKOUT_FAILURE_THRESHOLD, PASSCODE_LOCKOUT_INITIAL_MS, PASSCODE_LOCKOUT_MAX_MS, RecoveryAttestationStatus, RestQueryError, RpcConnectionError, UKDR_DECIMALS, UKDR_DISPLAY_DENOM, UKDR_MINIMAL_DENOM, VAULT_LEGACY_KEY, WALLETCONNECT_COSMOS_METHODS, WALLETCONNECT_COSMOS_NAMESPACE, WEBAUTHN_RP_NAME, WalletAccountError, WalletConnectNotInitializedError, WalletConnectSessionError, WalletConnectSigningError, WalletConnectionError, WalletConnectionRejectedError, WalletNotInstalledError, WebAuthnUnavailableError, WebAuthnUserCancelledError, acknowledgeEmbeddedBackup, addressFromHdMnemonic, addressFromPrivateKey, assertPasscodeAllowedForCreation, assertPasscodeUnlockAllowed, assertPasskey, assertValidPasscode, assertValidRecoveryMnemonic, assertVaultPermitsTransaction, attestationSignPayload, broadcastAndConfirmTx, buildClaimRewardMsg, buildKingdomChainInfo, buildRequiredCosmosNamespaces, buildSendUkdrMsg, buildSubmitApplicationMsg, citizenTxErrorMessage, clearEmbeddedWallet, clearPasscodeLockoutRecord, clearVaultFromIndexedDb, computePasscodeLockoutDurationMs, connectCosmostation, connectKeplr, connectLeap, connectWalletConnect, createBrowserSigningClient, createEmbeddedWallet, createHdDerivedPlaintext, createKingdomChainRegistry, createPasskeyMaterialFromAssertion, createPbkdf2Salt, createWalletConnectOfflineSigner, decodeCredentialId, decodeDirectEntropyMnemonic, decryptWalletPayload, defaultEmbeddedHdPath, defaultUkdrTxFee, deriveKekFromPasscode, deriveKekFromPbkdf2, deriveKekFromPrf, derivePrivateKeyFromHdMnemonic, detectRecoveryMnemonicKeyType, detectWebAuthnPrfCapabilities, disconnectWalletConnect, downloadEmbeddedBackupFile, embeddedPlaintextToSigner, enableEmbeddedPasskeyUnlock, encodeCredentialId, encodeDirectEntropyMnemonic, encryptWalletPayload, evaluatePasscodeStrength, exportEncryptedBackup, fetchFeeGrantGranter, fetchUkdrBalance, fetchUnclaimedFinalizedRewards, formatUkdrAsKdr, getCosmostationKeplrApi, getEmbeddedOfflineSigner, getEmbeddedWalletSession, getPasscodeLockoutState, hasEmbeddedWallet, hasLegacyEmbeddedWallet, hasMixedCharacterClasses, importEmbeddedBackup, initWalletConnectClient, isCosmostationAvailable, isKeplrAvailable, isLeapAvailable, loadPasscodeLockoutRecord, loadVaultFromIndexedDb, lockEmbeddedWallet, markVaultBackupAcknowledged, migrateLegacyEmbeddedWallet, normalizePasscode, normalizeRecoveryMnemonic, parseEncryptedBackup, parseKdrToUkdr, parseWalletConnectAccount, plaintextFromRecoveryMnemonic, providerSeedFromHex, publicKeyFromPrivateSeed, readPrfOutput, recordPasscodeUnlockFailure, recordPasscodeUnlockSuccess, recoverEmbeddedWalletFromMnemonic, recoveryMnemonicAddress, recoveryMnemonicFromPlaintext, registerPasskey, resolvePlaintextKeyType, resolveVaultStorageKey, restoreWalletConnectSession, revealEmbeddedRecoveryPhrase, savePasscodeLockoutRecord, saveVaultToIndexedDb, selectEmbeddedWalletKdf, serializeBackupFile, signAttestationPayload, signCitizenshipAttestation, suggestAndConnect, toWalletConnectCosmosChainId, ukdrCoin, unlockEmbeddedWallet, validateChainConfig, vaultUsesPasscodeUnlock, vaultUsesPasskeyUnlock };
|
|
3119
3389
|
//# sourceMappingURL=index.js.map
|
|
3120
3390
|
//# sourceMappingURL=index.js.map
|