@idos-network/kwil-infra 1.1.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/.turbo/turbo-build.log +47 -0
- package/.turbo/turbo-test.log +126 -0
- package/.turbo/turbo-typecheck.log +5 -0
- package/CHANGELOG.md +20 -0
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/dist/actions/index.d.mts +2 -0
- package/dist/actions/index.mjs +1371 -0
- package/dist/actions/index.mjs.map +1 -0
- package/dist/facesign/index.d.mts +2 -0
- package/dist/facesign/index.mjs +2 -0
- package/dist/facesign-signer-ADd4EASX.d.mts +29 -0
- package/dist/facesign-signer-ADd4EASX.d.mts.map +1 -0
- package/dist/facesign-signer-BY9Nti9F.mjs +244 -0
- package/dist/facesign-signer-BY9Nti9F.mjs.map +1 -0
- package/dist/index-Ci6QhKJo.d.mts +644 -0
- package/dist/index-Ci6QhKJo.d.mts.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +429 -0
- package/dist/index.mjs.map +1 -0
- package/dist/signature-verification/index.d.mts +14 -0
- package/dist/signature-verification/index.d.mts.map +1 -0
- package/dist/signature-verification/index.mjs +140 -0
- package/dist/signature-verification/index.mjs.map +1 -0
- package/dist/xrp/utils.d.mts +1165 -0
- package/dist/xrp/utils.d.mts.map +1 -0
- package/dist/xrp/utils.mjs +105 -0
- package/dist/xrp/utils.mjs.map +1 -0
- package/dist/xrpl-credentials/index.d.mts +179 -0
- package/dist/xrpl-credentials/index.d.mts.map +1 -0
- package/dist/xrpl-credentials/index.mjs +224 -0
- package/dist/xrpl-credentials/index.mjs.map +1 -0
- package/package.json +93 -0
- package/src/actions/actions.ts +2197 -0
- package/src/actions/index.ts +55 -0
- package/src/create-kwil-client.ts +144 -0
- package/src/create-kwil-signer.ts +270 -0
- package/src/facesign/facesign-signer.ts +327 -0
- package/src/facesign/index.ts +2 -0
- package/src/index.ts +7 -0
- package/src/near/create-near-wallet-kwil-signer.ts +245 -0
- package/src/near/get-config.ts +43 -0
- package/src/near/nep413.ts +62 -0
- package/src/near/signature-verification.ts +85 -0
- package/src/signature-verification/evm.ts +33 -0
- package/src/signature-verification/facesign.ts +19 -0
- package/src/signature-verification/index.test.ts +110 -0
- package/src/signature-verification/index.ts +72 -0
- package/src/signature-verification/stellar.ts +31 -0
- package/src/xrp/signature-verification.ts +18 -0
- package/src/xrp/signer.ts +43 -0
- package/src/xrp/utils.ts +178 -0
- package/src/xrpl-credentials/accept.ts +143 -0
- package/src/xrpl-credentials/create.ts +199 -0
- package/src/xrpl-credentials/index.ts +12 -0
- package/tsconfig.json +33 -0
- package/tsdown.config.ts +13 -0
- package/vitest.config.ts +6 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import invariant from "tiny-invariant";
|
|
2
|
+
import { borshDeserialize, borshSerialize, bs58Decode, hexDecode, hexEncode, sha256Hash, utf8Encode } from "@idos-network/utils/codecs";
|
|
3
|
+
import nacl from "tweetnacl";
|
|
4
|
+
//#region src/near/signature-verification.ts
|
|
5
|
+
const verifyNearSignature = async (message, signature, publicKey) => {
|
|
6
|
+
try {
|
|
7
|
+
const pieces = publicKey.split(":");
|
|
8
|
+
if (pieces.length !== 2 || pieces[0] !== "ed25519") {
|
|
9
|
+
console.warn("Invalid NEAR public key format:", publicKey);
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
const publicKeyBytes = bs58Decode(pieces[1]);
|
|
13
|
+
if (publicKeyBytes.length !== 32) {
|
|
14
|
+
console.warn("Invalid NEAR public key length:", publicKeyBytes.length);
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const signatureBytes = hexDecode(signature);
|
|
18
|
+
const payloadLength = new DataView(signatureBytes.buffer).getUint16(0, false);
|
|
19
|
+
const payloadBytes = signatureBytes.slice(2, 2 + payloadLength);
|
|
20
|
+
const actualSignature = signatureBytes.slice(2 + payloadLength);
|
|
21
|
+
if (actualSignature.length !== 64) {
|
|
22
|
+
console.warn("Invalid signature length:", actualSignature.length);
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const payloadSchema = { struct: {
|
|
26
|
+
tag: "u32",
|
|
27
|
+
message: "string",
|
|
28
|
+
nonce: { array: {
|
|
29
|
+
type: "u8",
|
|
30
|
+
len: 32
|
|
31
|
+
} },
|
|
32
|
+
recipient: "string",
|
|
33
|
+
callbackUrl: { option: "string" }
|
|
34
|
+
} };
|
|
35
|
+
const deserializedPayload = borshDeserialize(payloadSchema, payloadBytes);
|
|
36
|
+
const hash = sha256Hash(borshSerialize(payloadSchema, {
|
|
37
|
+
tag: 2147484061,
|
|
38
|
+
message,
|
|
39
|
+
nonce: deserializedPayload.nonce,
|
|
40
|
+
recipient: deserializedPayload.recipient,
|
|
41
|
+
callbackUrl: deserializedPayload.callbackUrl
|
|
42
|
+
}));
|
|
43
|
+
return nacl.sign.detached.verify(hash, actualSignature, publicKeyBytes);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.warn("NEAR signature verification failed:", error);
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/xrp/signature-verification.ts
|
|
51
|
+
const verifyRippleSignature = async (message, signature, publicKey) => {
|
|
52
|
+
let xrpKeypair;
|
|
53
|
+
try {
|
|
54
|
+
xrpKeypair = await import("ripple-keypairs");
|
|
55
|
+
} catch (e) {
|
|
56
|
+
throw new Error("Can't load `ripple-keypairs`", { cause: e });
|
|
57
|
+
}
|
|
58
|
+
const messageHex = hexEncode(utf8Encode(message));
|
|
59
|
+
return xrpKeypair.verify(messageHex, signature, publicKey);
|
|
60
|
+
};
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/signature-verification/evm.ts
|
|
63
|
+
const verifyEvmSignature = async (message, signature, address) => {
|
|
64
|
+
let wagmi;
|
|
65
|
+
try {
|
|
66
|
+
wagmi = await import("@wagmi/core");
|
|
67
|
+
} catch (_e) {
|
|
68
|
+
throw new Error("Can't load @wagmi/core");
|
|
69
|
+
}
|
|
70
|
+
let chains;
|
|
71
|
+
try {
|
|
72
|
+
chains = await import("@wagmi/core/chains");
|
|
73
|
+
} catch (_e) {
|
|
74
|
+
throw new Error("Can't load @wagmi/core/chains");
|
|
75
|
+
}
|
|
76
|
+
const wagmiConfig = wagmi.createConfig({
|
|
77
|
+
chains: [chains.mainnet],
|
|
78
|
+
transports: { [chains.mainnet.id]: wagmi.http() }
|
|
79
|
+
});
|
|
80
|
+
return wagmi.verifyMessage(wagmiConfig, {
|
|
81
|
+
address,
|
|
82
|
+
message,
|
|
83
|
+
signature
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/signature-verification/facesign.ts
|
|
88
|
+
const verifyFaceSignSignature = (message, signature, publicKey) => {
|
|
89
|
+
try {
|
|
90
|
+
return nacl.sign.detached.verify(utf8Encode(message), hexDecode(signature), hexDecode(publicKey));
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.warn("FaceSign signature verification failed:", error);
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/signature-verification/stellar.ts
|
|
98
|
+
const verifyStellarSignature = async (message, signature, publicKey) => {
|
|
99
|
+
let stellar;
|
|
100
|
+
try {
|
|
101
|
+
stellar = await import("@stellar/stellar-sdk");
|
|
102
|
+
} catch (e) {
|
|
103
|
+
throw new Error("Can't load `@stellar/stellar-sdk`", { cause: e });
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
const signatureBuffer = Buffer.from(signature, "hex");
|
|
107
|
+
const publicKeyBuffer = Buffer.from(publicKey, "hex");
|
|
108
|
+
const strKeyAddress = stellar.StrKey.encodeEd25519PublicKey(publicKeyBuffer);
|
|
109
|
+
return stellar.Keypair.fromPublicKey(strKeyAddress).verify(Buffer.from(message), signatureBuffer);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.warn("Stellar signature verification failed:", error);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/signature-verification/index.ts
|
|
117
|
+
const verifySignature = async (walletPayload) => {
|
|
118
|
+
invariant(walletPayload.address, "Wallet address is required");
|
|
119
|
+
invariant(walletPayload.message, "Wallet message is required");
|
|
120
|
+
invariant(walletPayload.signature, "Wallet signature is required");
|
|
121
|
+
invariant(walletPayload.wallet_type, "Wallet type is required");
|
|
122
|
+
if (walletPayload.wallet_type !== "EVM") invariant(walletPayload.public_key?.[0], "Wallet public_key is required for non-EVM wallets");
|
|
123
|
+
try {
|
|
124
|
+
switch (walletPayload.wallet_type) {
|
|
125
|
+
case "EVM": return verifyEvmSignature(walletPayload.message, walletPayload.signature, walletPayload.address);
|
|
126
|
+
case "NEAR": return verifyNearSignature(walletPayload.message, walletPayload.signature, walletPayload.public_key[0]);
|
|
127
|
+
case "XRPL": return verifyRippleSignature(walletPayload.message, walletPayload.signature, walletPayload.public_key[0]);
|
|
128
|
+
case "Stellar": return await verifyStellarSignature(walletPayload.message, walletPayload.signature, walletPayload.public_key[0]);
|
|
129
|
+
case "FaceSign": return verifyFaceSignSignature(walletPayload.message, walletPayload.signature, walletPayload.public_key[0]);
|
|
130
|
+
default: throw new Error(`Unsupported wallet type: ${walletPayload.wallet_type}`);
|
|
131
|
+
}
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.warn("Error verifying signature", error);
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
//#endregion
|
|
138
|
+
export { verifySignature };
|
|
139
|
+
|
|
140
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/near/signature-verification.ts","../../src/xrp/signature-verification.ts","../../src/signature-verification/evm.ts","../../src/signature-verification/facesign.ts","../../src/signature-verification/stellar.ts","../../src/signature-verification/index.ts"],"sourcesContent":["import {\n borshDeserialize,\n borshSerialize,\n bs58Decode,\n hexDecode,\n sha256Hash,\n} from \"@idos-network/utils/codecs\";\nimport nacl from \"tweetnacl\";\n\ninterface NEP413Payload {\n tag: number;\n message: string;\n nonce: number[];\n recipient: string;\n callbackUrl?: string;\n}\n\nexport const verifyNearSignature = async (\n message: string,\n signature: string,\n publicKey: string,\n): Promise<boolean> => {\n try {\n // Parse the NEAR public key format: \"ed25519:base58_encoded_key\"\n const pieces = publicKey.split(\":\");\n if (pieces.length !== 2 || pieces[0] !== \"ed25519\") {\n console.warn(\"Invalid NEAR public key format:\", publicKey);\n return false;\n }\n\n // Extract raw public key bytes (am trying to match the logic I did in Backend)\n const publicKeyBytes = bs58Decode(pieces[1]);\n if (publicKeyBytes.length !== 32) {\n console.warn(\"Invalid NEAR public key length:\", publicKeyBytes.length);\n return false;\n }\n\n // Decode the signature from hex\n const signatureBytes = hexDecode(signature);\n\n // Deserialize the signature (matching Go's deserializeSignature)\n const payloadLength = new DataView(signatureBytes.buffer).getUint16(0, false);\n const payloadBytes = signatureBytes.slice(2, 2 + payloadLength);\n const actualSignature = signatureBytes.slice(2 + payloadLength);\n\n if (actualSignature.length !== 64) {\n console.warn(\"Invalid signature length:\", actualSignature.length);\n return false;\n }\n\n // Deserialize the payload to extract nonce, recipient, callbackUrl\n const payloadSchema = {\n struct: {\n tag: \"u32\",\n message: \"string\",\n nonce: { array: { type: \"u8\", len: 32 } },\n recipient: \"string\",\n callbackUrl: { option: \"string\" },\n },\n };\n\n const deserializedPayload = borshDeserialize(payloadSchema, payloadBytes) as NEP413Payload;\n\n // Reconstruct the payload with tag and message (matching Go implementation)\n const reconstructedPayload: NEP413Payload = {\n tag: 2147484061, // 2**31 + 413\n message: message, // Use the provided message\n nonce: deserializedPayload.nonce,\n recipient: deserializedPayload.recipient,\n callbackUrl: deserializedPayload.callbackUrl,\n };\n\n // Serialize the entire payload (matching Go's borsch.Serialize(*payload))\n const fullPayloadBytes = borshSerialize(payloadSchema, reconstructedPayload);\n // Hash the payload (matching Go's sha256.Sum256(payloadBytes))\n const hash = sha256Hash(fullPayloadBytes);\n // Raw ed25519 verification using nacl (matching Go's ed25519.Verify)\n const isValid = nacl.sign.detached.verify(hash, actualSignature, publicKeyBytes);\n\n return isValid;\n } catch (error) {\n console.warn(\"NEAR signature verification failed:\", error);\n return false;\n }\n};\n","import { hexEncode, utf8Encode } from \"@idos-network/utils/codecs\";\n\nexport const verifyRippleSignature = async (\n message: string,\n signature: string,\n publicKey: string,\n): Promise<boolean> => {\n let xrpKeypair: typeof import(\"ripple-keypairs\");\n\n try {\n xrpKeypair = await import(\"ripple-keypairs\");\n } catch (e) {\n throw new Error(\"Can't load `ripple-keypairs`\", { cause: e });\n }\n\n const messageHex = hexEncode(utf8Encode(message));\n return xrpKeypair.verify(messageHex, signature, publicKey);\n};\n","export const verifyEvmSignature = async (\n message: string,\n signature: `0x${string}`,\n address: `0x${string}`,\n): Promise<boolean> => {\n let wagmi: typeof import(\"@wagmi/core\");\n\n try {\n wagmi = await import(\"@wagmi/core\");\n } catch (_e) {\n throw new Error(\"Can't load @wagmi/core\");\n }\n\n let chains: typeof import(\"@wagmi/core/chains\");\n try {\n chains = await import(\"@wagmi/core/chains\");\n } catch (_e) {\n throw new Error(\"Can't load @wagmi/core/chains\");\n }\n\n const wagmiConfig = wagmi.createConfig({\n chains: [chains.mainnet],\n transports: {\n [chains.mainnet.id]: wagmi.http(),\n },\n });\n\n return wagmi.verifyMessage(wagmiConfig, {\n address,\n message,\n signature,\n });\n};\n","import { hexDecode, utf8Encode } from \"@idos-network/utils/codecs\";\nimport nacl from \"tweetnacl\";\n\nexport const verifyFaceSignSignature = (\n message: string,\n signature: string,\n publicKey: string,\n): boolean => {\n try {\n return nacl.sign.detached.verify(\n utf8Encode(message),\n hexDecode(signature),\n hexDecode(publicKey),\n );\n } catch (error) {\n console.warn(\"FaceSign signature verification failed:\", error);\n return false;\n }\n};\n","export const verifyStellarSignature = async (\n message: string,\n signature: string,\n publicKey: string,\n): Promise<boolean> => {\n let stellar: typeof import(\"@stellar/stellar-sdk\");\n\n try {\n stellar = await import(\"@stellar/stellar-sdk\");\n } catch (e) {\n throw new Error(\"Can't load `@stellar/stellar-sdk`\", { cause: e });\n }\n\n try {\n // Convert hex signature to buffer\n const signatureBuffer = Buffer.from(signature, \"hex\");\n\n // `Keypair.fromPublicKey()` expects StrKey format, but we're passing as hex (derivePublicKey result).\n const publicKeyBuffer = Buffer.from(publicKey, \"hex\");\n const strKeyAddress = stellar.StrKey.encodeEd25519PublicKey(publicKeyBuffer);\n\n const keypair = stellar.Keypair.fromPublicKey(strKeyAddress);\n\n const result = keypair.verify(Buffer.from(message), signatureBuffer);\n\n return result;\n } catch (error) {\n console.warn(\"Stellar signature verification failed:\", error);\n return false;\n }\n};\n","import invariant from \"tiny-invariant\";\n\nimport type { WalletType } from \"../actions\";\n\nimport { verifyNearSignature } from \"../near/signature-verification\";\nimport { verifyRippleSignature } from \"../xrp/signature-verification\";\nimport { verifyEvmSignature } from \"./evm\";\nimport { verifyFaceSignSignature } from \"./facesign\";\nimport { verifyStellarSignature } from \"./stellar\";\n\nexport interface WalletSignature {\n address: string;\n signature: string;\n message: string;\n wallet_type: WalletType;\n public_key?: string[];\n}\n\nexport const verifySignature = async (walletPayload: WalletSignature): Promise<boolean> => {\n invariant(walletPayload.address, \"Wallet address is required\");\n invariant(walletPayload.message, \"Wallet message is required\");\n invariant(walletPayload.signature, \"Wallet signature is required\");\n invariant(walletPayload.wallet_type, \"Wallet type is required\");\n\n if (walletPayload.wallet_type !== \"EVM\") {\n invariant(walletPayload.public_key?.[0], \"Wallet public_key is required for non-EVM wallets\");\n }\n\n try {\n switch (walletPayload.wallet_type) {\n case \"EVM\":\n return verifyEvmSignature(\n walletPayload.message,\n walletPayload.signature as `0x${string}`,\n walletPayload.address as `0x${string}`,\n );\n case \"NEAR\":\n return verifyNearSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n case \"XRPL\":\n return verifyRippleSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n case \"Stellar\":\n return await verifyStellarSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n case \"FaceSign\":\n return verifyFaceSignSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n default:\n throw new Error(`Unsupported wallet type: ${walletPayload.wallet_type}`);\n }\n } catch (error) {\n console.warn(\"Error verifying signature\", error);\n return false;\n }\n};\n"],"mappings":"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"}
|