diff --git a/api/typeDefs/wallet.js b/api/typeDefs/wallet.js
index 061ec837b0..809f49f530 100644
--- a/api/typeDefs/wallet.js
+++ b/api/typeDefs/wallet.js
@@ -119,6 +119,16 @@ const typeDefs = gql`
noffer: String!
): WalletRecvClink!
+ upsertWalletSendSpark(
+ ${shared},
+ mnemonic: VaultEntryInput!
+ ): WalletSendSpark!
+
+ upsertWalletRecvSpark(
+ ${shared},
+ identityPublicKey: String!
+ ): WalletRecvSpark!
+
# tests
testWalletRecvNWC(
url: String!
@@ -159,6 +169,10 @@ const typeDefs = gql`
noffer: String!
): Boolean!
+ testWalletRecvSpark(
+ identityPublicKey: String!
+ ): Boolean!
+
# delete
deleteWallet(id: ID!): Boolean
@@ -235,6 +249,7 @@ const typeDefs = gql`
| WalletSendLNC
| WalletSendCLNRest
| WalletSendClink
+ | WalletSendSpark
| WalletRecvNWC
| WalletRecvLNbits
| WalletRecvPhoenixd
@@ -243,6 +258,7 @@ const typeDefs = gql`
| WalletRecvCLNRest
| WalletRecvLNDGRPC
| WalletRecvClink
+ | WalletRecvSpark
type WalletSettings {
receiveCreditsBelowSats: Int!
@@ -309,6 +325,11 @@ const typeDefs = gql`
secretKey: VaultEntry!
}
+ type WalletSendSpark {
+ id: ID!
+ mnemonic: VaultEntry!
+ }
+
type WalletRecvNWC {
id: ID!
url: String!
@@ -356,6 +377,11 @@ const typeDefs = gql`
noffer: String!
}
+ type WalletRecvSpark {
+ id: ID!
+ identityPublicKey: String!
+ }
+
input AutowithdrawSettings {
autoWithdrawThreshold: Int!
autoWithdrawMaxFeePercent: Float!
diff --git a/package-lock.json b/package-lock.json
index 9779d4db78..3788bad1bb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
"@apollo/server": "^4.11.0",
"@as-integrations/next": "^3.1.0",
"@auth/prisma-adapter": "^2.7.0",
+ "@buildonspark/spark-sdk": "^0.4.2",
"@cashu/cashu-ts": "^2.4.1",
"@graphql-tools/schema": "^10.0.6",
"@lightninglabs/lnc-web": "^0.3.2-alpha",
@@ -31,6 +32,7 @@
"async-retry": "^1.3.3",
"aws-sdk": "^2.1691.0",
"bech32": "^2.0.0",
+ "bip39": "^3.1.0",
"bolt11": "^1.4.1",
"bootstrap": "^5.3.3",
"canonical-json": "0.0.4",
@@ -2438,6 +2440,152 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
"dev": true
},
+ "node_modules/@bitcoinerlab/secp256k1": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@bitcoinerlab/secp256k1/-/secp256k1-1.2.0.tgz",
+ "integrity": "sha512-jeujZSzb3JOZfmJYI0ph1PVpCRV5oaexCgy+RvCXV8XlY+XFB/2n3WOcvBsKLsOw78KYgnQrQWb2HrKE4be88Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/curves": "^1.7.0"
+ }
+ },
+ "node_modules/@bufbuild/protobuf": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.10.0.tgz",
+ "integrity": "sha512-fdRs9PSrBF7QUntpZpq6BTw58fhgGJojgg39m9oFOJGZT+nip9b0so5cYY1oWl5pvemDLr0cPPsH46vwThEbpQ==",
+ "license": "(Apache-2.0 AND BSD-3-Clause)"
+ },
+ "node_modules/@buildonspark/spark-sdk": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@buildonspark/spark-sdk/-/spark-sdk-0.4.2.tgz",
+ "integrity": "sha512-d9Yf2oSvZ90iaRr4Fdo8UgDgZz3aKS3Yfa1/26WBmmJIwJp80jNREWgLi3ud6DOauPxngJTzvTUzfoWN24DmlQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@bitcoinerlab/secp256k1": "^1.1.1",
+ "@bufbuild/protobuf": "^2.2.5",
+ "@lightsparkdev/core": "^1.4.4",
+ "@noble/curves": "^1.8.0",
+ "@noble/hashes": "^1.7.0",
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/context-async-hooks": "^2.0.0",
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/instrumentation-fetch": "^0.203.0",
+ "@opentelemetry/instrumentation-undici": "^0.14.0",
+ "@opentelemetry/sdk-trace-base": "^2.0.0",
+ "@opentelemetry/sdk-trace-node": "^2.0.1",
+ "@opentelemetry/sdk-trace-web": "^2.0.1",
+ "@scure/base": "^1.2.4",
+ "@scure/bip32": "^1.6.2",
+ "@scure/bip39": "^1.5.4",
+ "@scure/btc-signer": "^1.5.0",
+ "abort-controller-x": "^0.4.3",
+ "abortcontroller-polyfill": "^1.7.8",
+ "async-mutex": "^0.5.0",
+ "bare-crypto": "^1.9.2",
+ "bare-fetch": "^2.4.1",
+ "buffer": "^6.0.3",
+ "eciesjs": "^0.4.13",
+ "eventemitter3": "^5.0.1",
+ "js-base64": "^3.7.7",
+ "light-bolt11-decoder": "^3.2.0",
+ "nice-grpc": "^2.1.10",
+ "nice-grpc-client-middleware-retry": "^3.1.10",
+ "nice-grpc-common": "^2.0.2",
+ "nice-grpc-opentelemetry": "^0.1.18",
+ "nice-grpc-web": "^3.3.7",
+ "ts-proto": "^2.6.1",
+ "uuidv7": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18.2.0",
+ "react-native": ">=0.71.0",
+ "react-native-get-random-values": ">=1.11.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ },
+ "react-native-get-random-values": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@buildonspark/spark-sdk/node_modules/@noble/curves": {
+ "version": "1.9.7",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz",
+ "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.8.0"
+ },
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@buildonspark/spark-sdk/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@buildonspark/spark-sdk/node_modules/@scure/base": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz",
+ "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@buildonspark/spark-sdk/node_modules/@scure/bip32": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz",
+ "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/curves": "~1.9.0",
+ "@noble/hashes": "~1.8.0",
+ "@scure/base": "~1.2.5"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@buildonspark/spark-sdk/node_modules/@scure/bip39": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz",
+ "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "~1.8.0",
+ "@scure/base": "~1.2.5"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@buildonspark/spark-sdk/node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "license": "MIT"
+ },
"node_modules/@cashu/cashu-ts": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/@cashu/cashu-ts/-/cashu-ts-2.4.1.tgz",
@@ -2523,6 +2671,20 @@
"url": "https://paulmillr.com/funding/"
}
},
+ "node_modules/@ecies/ciphers": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.4.tgz",
+ "integrity": "sha512-t+iX+Wf5nRKyNzk8dviW3Ikb/280+aEJAnw9YXvCp2tYGPSkMki+NRY+8aNLmVFv3eNtMdvViPNOPxS8SZNP+w==",
+ "license": "MIT",
+ "engines": {
+ "bun": ">=1",
+ "deno": ">=2",
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "@noble/ciphers": "^1.0.0"
+ }
+ },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.23.1",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz",
@@ -4233,6 +4395,38 @@
"crypto-js": "4.2.0"
}
},
+ "node_modules/@lightsparkdev/core": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/@lightsparkdev/core/-/core-1.4.5.tgz",
+ "integrity": "sha512-SQo1wNNMfJNFdZPFsbYOylEa6t5X9S+FnKneju9qbvWZz9vfsb6B+MkvVW7DUGoMhisjtPzmR691qedfvstWIg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "dayjs": "^1.11.7",
+ "graphql": "^16.6.0",
+ "graphql-ws": "^5.11.3",
+ "secp256k1": "^5.0.1",
+ "ws": "^8.12.1",
+ "zen-observable-ts": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@lightsparkdev/core/node_modules/secp256k1": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-5.0.1.tgz",
+ "integrity": "sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "elliptic": "^6.5.7",
+ "node-addon-api": "^5.0.0",
+ "node-gyp-build": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/@next/env": {
"version": "14.2.25",
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.25.tgz",
@@ -4650,6 +4844,244 @@
"yarn": "^1.22.10"
}
},
+ "node_modules/@opentelemetry/api": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
+ "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/context-async-hooks": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.2.0.tgz",
+ "integrity": "sha512-qRkLWiUEZNAmYapZ7KGS5C4OmBLcP/H2foXeOEaowYCR0wi89fHejrfYfbuLVCMLp/dWZXKvQusdbUEZjERfwQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz",
+ "integrity": "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "import-in-the-middle": "^1.8.1",
+ "require-in-the-middle": "^7.1.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fetch": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fetch/-/instrumentation-fetch-0.203.0.tgz",
+ "integrity": "sha512-Z+mls3rOP2BaVykDZLLZPvchjj9l2oj3dYG1GTnrc27Y8o3biE+5M1b0izblycbbQHXjMPHQCpmjHbLMQuWtBg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/instrumentation": "0.203.0",
+ "@opentelemetry/sdk-trace-web": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fetch/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fetch/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fetch/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fetch/node_modules/@opentelemetry/sdk-trace-web": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-web/-/sdk-trace-web-2.0.1.tgz",
+ "integrity": "sha512-R4/i0rISvAujG4Zwk3s6ySyrWG+Db3SerZVM4jZ2lEzjrNylF7nRAy1hVvWe8gTbwIxX+6w6ZvZwdtl2C7UQHQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-undici": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.14.0.tgz",
+ "integrity": "sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/instrumentation": "^0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/resources": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz",
+ "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.2.0.tgz",
+ "integrity": "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/resources": "2.2.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-node": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.2.0.tgz",
+ "integrity": "sha512-+OaRja3f0IqGG2kptVeYsrZQK9nKRSpfFrKtRBq4uh6nIB8bTBgaGvYQrQoRrQWQMA5dK5yLhDMDc0dvYvCOIQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/context-async-hooks": "2.2.0",
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/sdk-trace-base": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-web": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-web/-/sdk-trace-web-2.2.0.tgz",
+ "integrity": "sha512-x/LHsDBO3kfqaFx5qSzBljJ5QHsRXrvS4MybBDy1k7Svidb8ZyIPudWVzj3s5LpPkYZIgi9e+7tdsNCnptoelw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.2.0",
+ "@opentelemetry/sdk-trace-base": "2.2.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.37.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.37.0.tgz",
+ "integrity": "sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/@panva/hkdf": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz",
@@ -5322,6 +5754,57 @@
"url": "https://paulmillr.com/funding/"
}
},
+ "node_modules/@scure/btc-signer": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@scure/btc-signer/-/btc-signer-1.8.1.tgz",
+ "integrity": "sha512-8nX9T++dFyKpvqksNHfSi9CgRsGnHAQtCdIQ1y1GmbCGLpV97v4MUyemUUT6uDumKL3oo3m4niyY6A32nmdLuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/curves": "~1.9.0",
+ "@noble/hashes": "~1.8.0",
+ "@scure/base": "~1.2.5",
+ "micro-packed": "~0.7.3"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/btc-signer/node_modules/@noble/curves": {
+ "version": "1.9.7",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz",
+ "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.8.0"
+ },
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/btc-signer/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/btc-signer/node_modules/@scure/base": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz",
+ "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/@shocknet/clink-sdk": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@shocknet/clink-sdk/-/clink-sdk-1.4.0.tgz",
@@ -6607,6 +7090,18 @@
"react-dom": "^17 || ^18"
}
},
+ "node_modules/abort-controller-x": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.4.3.tgz",
+ "integrity": "sha512-VtUwTNU8fpMwvWGn4xE93ywbogTYsuT+AUxAXOeelbXuQVIwNmC5YLeho9sH4vZ4ITW8414TTAOG1nW6uIVHCA==",
+ "license": "MIT"
+ },
+ "node_modules/abortcontroller-polyfill": {
+ "version": "1.7.8",
+ "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.8.tgz",
+ "integrity": "sha512-9f1iZ2uWh92VcrU9Y8x+LdM4DLj75VE0MJB8zuF1iUnroEptStw+DQ8EQPMUdfe5k+PkB1uUfDQfWbhstH8LrQ==",
+ "license": "MIT"
+ },
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -6620,9 +7115,10 @@
}
},
"node_modules/acorn": {
- "version": "8.12.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
- "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@@ -7103,6 +7599,20 @@
"node": ">= 6"
}
},
+ "node_modules/b4a": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz",
+ "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "react-native-b4a": "*"
+ },
+ "peerDependenciesMeta": {
+ "react-native-b4a": {
+ "optional": true
+ }
+ }
+ },
"node_modules/babel-jest": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
@@ -7300,43 +7810,240 @@
"@babel/core": "^7.0.0"
}
},
- "node_modules/babel-preset-jest": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
- "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
- "dev": true,
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/bail": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+ "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/barcode-detector": {
+ "version": "2.2.11",
+ "resolved": "https://registry.npmjs.org/barcode-detector/-/barcode-detector-2.2.11.tgz",
+ "integrity": "sha512-N50XZ6Rav2sxTgHXOc38/mkpVJMan11GZ8Yqi1pPMZpTJSXuZ/FpIee6OtLehZX/Vs4ZOzGbp1DgXzFCfKggWA==",
+ "dependencies": {
+ "@types/dom-webcodecs": "^0.1.13",
+ "zxing-wasm": "1.2.14"
+ }
+ },
+ "node_modules/bare-crypto": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/bare-crypto/-/bare-crypto-1.12.0.tgz",
+ "integrity": "sha512-GLeZOS2RQkEawVNPvBKmVZQWwSs4jLhculTvuOfLdP+RTMN1Gv3pz+oI9fcQj7/LE2QJM4cPOHfx4u0izBaTHA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-stream": "^2.6.3"
+ },
+ "peerDependencies": {
+ "bare-buffer": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-buffer": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/bare-dns": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/bare-dns/-/bare-dns-2.1.4.tgz",
+ "integrity": "sha512-abwjHmpWqSRNB7V5615QxPH92L71AVzFm/kKTs8VYiNTAi2xVdonpv0BjJ0hwXLwomoW+xsSOPjW6PZPO14asg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "bare": ">=1.7.0"
+ }
+ },
+ "node_modules/bare-events": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.1.tgz",
+ "integrity": "sha512-oxSAxTS1hRfnyit2CL5QpAOS5ixfBjj6ex3yTNvXyY/kE719jQ/IjuESJBK2w5v4wwQRAHGseVJXx9QBYOtFGQ==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "bare-abort-controller": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-abort-controller": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/bare-fetch": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/bare-fetch/-/bare-fetch-2.5.0.tgz",
+ "integrity": "sha512-2f/mx0hw4CDH2yX2cT7tVZGPnXcUswZCYu/EY72hHfbAipZJwZtDl8f3DsXJG+yXyPBNw3TNPicMbYPpfuaIfw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-form-data": "^1.1.3",
+ "bare-http1": "^4.0.2",
+ "bare-https": "^2.0.0",
+ "bare-stream": "^2.7.0",
+ "bare-zlib": "^1.3.0"
+ },
+ "peerDependencies": {
+ "bare-buffer": "*",
+ "bare-url": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-buffer": {
+ "optional": true
+ },
+ "bare-url": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/bare-form-data": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/bare-form-data/-/bare-form-data-1.1.6.tgz",
+ "integrity": "sha512-q1IN7dVo/lEhTlVkVQdULZvoBx6eTI94co0NtO7/A3JLFL/aZGA1wAHgcNEPrlkqTK9jTEdtzQXSoqGzlVjzgg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-stream": "^2.6.5"
+ }
+ },
+ "node_modules/bare-http-parser": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/bare-http-parser/-/bare-http-parser-1.0.0.tgz",
+ "integrity": "sha512-ZI3EFTFp8gHshWlUWl1vZo7KdZgH1hf/mNNDm+9pDVC5fk2dIfKGPQIEciBq3cIWR4JqDQTa6qCxPCqHqVel2g==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/bare-http1": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/bare-http1/-/bare-http1-4.1.5.tgz",
+ "integrity": "sha512-YT6tf5R7eIt1VBBc/mpNDXqbxl21WoYGdBXT5anQz2Xt4G2w2gKjmlkDPFwDARZd5wmgH5D2iIiRWAKwbKgVTQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-events": "^2.6.0",
+ "bare-http-parser": "^1.0.0",
+ "bare-stream": "^2.3.0",
+ "bare-tcp": "^2.0.3"
+ },
+ "peerDependencies": {
+ "bare-buffer": "*",
+ "bare-url": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-buffer": {
+ "optional": true
+ },
+ "bare-url": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/bare-https": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/bare-https/-/bare-https-2.1.0.tgz",
+ "integrity": "sha512-Sk3RUhXr7rt1Yq4im6xoGYGKz06denjsqM60igKA0IK6Kd3qDlLLZogrWsh3hDsB2kKt60092G3SIMoD9PAR6g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-http1": "^4.0.0",
+ "bare-tcp": "^2.0.0",
+ "bare-tls": "^2.0.0"
+ }
+ },
+ "node_modules/bare-net": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/bare-net/-/bare-net-2.2.0.tgz",
+ "integrity": "sha512-UF7cAbHsGE+H6uEqWF5IULBow1x58chZz4g3ALgHtv7wZsFcCbRDt0JKWEumf5Oma3QWS1Q6aLi0Rpll8RElMg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-events": "^2.2.2",
+ "bare-pipe": "^4.0.0",
+ "bare-stream": "^2.0.0",
+ "bare-tcp": "^2.0.0"
+ }
+ },
+ "node_modules/bare-pipe": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bare-pipe/-/bare-pipe-4.1.0.tgz",
+ "integrity": "sha512-0TD3NUIhh7KgPMRLyEBqSXlTZ8X/jcw1ulAjmErDWwoLdIF9FdVXvbpbzyKIl45sr9ZQ4k5AKThAOlrrtZcrXg==",
+ "license": "Apache-2.0",
"dependencies": {
- "babel-plugin-jest-hoist": "^29.6.3",
- "babel-preset-current-node-syntax": "^1.0.0"
+ "bare-events": "^2.0.0",
+ "bare-stream": "^2.0.0"
},
"engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ "bare": ">=1.16.0"
+ }
+ },
+ "node_modules/bare-stream": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz",
+ "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "streamx": "^2.21.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0"
+ "bare-buffer": "*",
+ "bare-events": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-buffer": {
+ "optional": true
+ },
+ "bare-events": {
+ "optional": true
+ }
}
},
- "node_modules/bail": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
- "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/bare-tcp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/bare-tcp/-/bare-tcp-2.1.0.tgz",
+ "integrity": "sha512-5DpPDWxJJ/pdbY4aMFPKBQvEizjvmgKOO75D/V0ELpLvauIuSAS0cWcZoqNPI3rAIYqIjpBu+xGLXHavjG67hw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-dns": "^2.0.4",
+ "bare-events": "^2.5.4",
+ "bare-stream": "^2.6.4"
+ },
+ "engines": {
+ "bare": ">=1.16.0"
}
},
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ "node_modules/bare-tls": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/bare-tls/-/bare-tls-2.1.5.tgz",
+ "integrity": "sha512-ouc6RqjizIRsUQJcboUI6GiIvwUr30F9xTPzyWFrDpkA1iDsWitLC/mSHjeVXU1H58rvFvnH1xENY8vhJH5e6A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-net": "^2.0.1",
+ "bare-stream": "^2.6.4"
+ },
+ "engines": {
+ "bare": ">=1.7.0"
+ }
},
- "node_modules/barcode-detector": {
- "version": "2.2.11",
- "resolved": "https://registry.npmjs.org/barcode-detector/-/barcode-detector-2.2.11.tgz",
- "integrity": "sha512-N50XZ6Rav2sxTgHXOc38/mkpVJMan11GZ8Yqi1pPMZpTJSXuZ/FpIee6OtLehZX/Vs4ZOzGbp1DgXzFCfKggWA==",
+ "node_modules/bare-zlib": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/bare-zlib/-/bare-zlib-1.3.1.tgz",
+ "integrity": "sha512-VP93GFzhrTdWh9mXNocn7XsP/nF5JQluiiSsbTvsQ4yIYlhEHRMF9lQmZZDXwzK9PNYaVGUV1bdQuqp0Mj7MHw==",
+ "license": "Apache-2.0",
"dependencies": {
- "@types/dom-webcodecs": "^0.1.13",
- "zxing-wasm": "1.2.14"
+ "bare-stream": "^2.0.0"
}
},
"node_modules/base-x": {
@@ -7439,6 +8146,27 @@
"node": ">=8.0.0"
}
},
+ "node_modules/bip39": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz",
+ "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==",
+ "license": "ISC",
+ "dependencies": {
+ "@noble/hashes": "^1.2.0"
+ }
+ },
+ "node_modules/bip39/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/bip66": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz",
@@ -7936,6 +8664,18 @@
"resolved": "https://registry.npmjs.org/canonical-json/-/canonical-json-0.0.4.tgz",
"integrity": "sha512-2sW7x0m/P7dqEnO0O87U7RTVQAaa7MELcd+Jd9FA6CYgYtwJ1TlDWIYMD8nuMkH1KoThsJogqgLyklrt9d/Azw=="
},
+ "node_modules/case-anything": {
+ "version": "2.1.13",
+ "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.13.tgz",
+ "integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
"node_modules/caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
@@ -8064,8 +8804,7 @@
"node_modules/cjs-module-lexer": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz",
- "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==",
- "dev": true
+ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ=="
},
"node_modules/classnames": {
"version": "2.5.1",
@@ -8857,6 +9596,12 @@
"url": "https://github.com/sponsors/kossnocorp"
}
},
+ "node_modules/dayjs": {
+ "version": "1.11.18",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
+ "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==",
+ "license": "MIT"
+ },
"node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
@@ -9168,6 +9913,15 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/dprint-node": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz",
+ "integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^1.0.3"
+ }
+ },
"node_modules/dset": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
@@ -9220,6 +9974,62 @@
"safe-buffer": "^5.0.1"
}
},
+ "node_modules/eciesjs": {
+ "version": "0.4.16",
+ "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.16.tgz",
+ "integrity": "sha512-dS5cbA9rA2VR4Ybuvhg6jvdmp46ubLn3E+px8cG/35aEDNclrqoCjg6mt0HYZ/M+OoESS3jSkCrqk1kWAEhWAw==",
+ "license": "MIT",
+ "dependencies": {
+ "@ecies/ciphers": "^0.2.4",
+ "@noble/ciphers": "^1.3.0",
+ "@noble/curves": "^1.9.7",
+ "@noble/hashes": "^1.8.0"
+ },
+ "engines": {
+ "bun": ">=1",
+ "deno": ">=2",
+ "node": ">=16"
+ }
+ },
+ "node_modules/eciesjs/node_modules/@noble/ciphers": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz",
+ "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/eciesjs/node_modules/@noble/curves": {
+ "version": "1.9.7",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz",
+ "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.8.0"
+ },
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/eciesjs/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/ecpair": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ecpair/-/ecpair-2.1.0.tgz",
@@ -10291,6 +11101,15 @@
"node": ">=0.8.x"
}
},
+ "node_modules/events-universal": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz",
+ "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bare-events": "^2.7.0"
+ }
+ },
"node_modules/execa": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
@@ -10467,6 +11286,12 @@
"node": ">=6.0.0"
}
},
+ "node_modules/fast-fifo": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
+ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
+ "license": "MIT"
+ },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -11122,6 +11947,18 @@
"graphql": ">=0.8.0"
}
},
+ "node_modules/graphql-ws": {
+ "version": "5.16.2",
+ "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.2.tgz",
+ "integrity": "sha512-E1uccsZxt/96jH/OwmLPuXMACILs76pKF2i3W861LpKBCYtGIyPQGtWLuBLkND4ox1KHns70e83PS4te50nvPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "graphql": ">=0.11 <=16"
+ }
+ },
"node_modules/har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@@ -11698,6 +12535,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/import-in-the-middle": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz",
+ "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.14.0",
+ "acorn-import-attributes": "^1.9.5",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
"node_modules/import-local": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
@@ -14484,6 +15333,12 @@
"url": "https://github.com/sponsors/panva"
}
},
+ "node_modules/js-base64": {
+ "version": "3.7.8",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.8.tgz",
+ "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/js-sha256": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz",
@@ -15446,6 +16301,27 @@
"resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.2.1.tgz",
"integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ=="
},
+ "node_modules/micro-packed": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.7.3.tgz",
+ "integrity": "sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg==",
+ "license": "MIT",
+ "dependencies": {
+ "@scure/base": "~1.2.5"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/micro-packed/node_modules/@scure/base": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz",
+ "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/micromark": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz",
@@ -16100,6 +16976,12 @@
"resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
"integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA=="
},
+ "node_modules/module-details-from-path": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz",
+ "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==",
+ "license": "MIT"
+ },
"node_modules/moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
@@ -16278,6 +17160,107 @@
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
"license": "ISC"
},
+ "node_modules/nice-grpc": {
+ "version": "2.1.13",
+ "resolved": "https://registry.npmjs.org/nice-grpc/-/nice-grpc-2.1.13.tgz",
+ "integrity": "sha512-IkXNok2NFyYh0WKp1aJFwFV3Ue2frBkJ16ojrmgX3Tc9n0g7r0VU+ur3H/leDHPPGsEeVozdMynGxYT30k3D/Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.14.0",
+ "abort-controller-x": "^0.4.0",
+ "nice-grpc-common": "^2.0.2"
+ }
+ },
+ "node_modules/nice-grpc-client-middleware-retry": {
+ "version": "3.1.12",
+ "resolved": "https://registry.npmjs.org/nice-grpc-client-middleware-retry/-/nice-grpc-client-middleware-retry-3.1.12.tgz",
+ "integrity": "sha512-CHKIeHznAePOsT2dLeGwoOFaybQz6LvkIsFfN8SLcyGyTR7AB6vZMaECJjx+QPL8O2qVgaVE167PdeOmQrPuag==",
+ "license": "MIT",
+ "dependencies": {
+ "abort-controller-x": "^0.4.0",
+ "nice-grpc-common": "^2.0.2"
+ }
+ },
+ "node_modules/nice-grpc-common": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/nice-grpc-common/-/nice-grpc-common-2.0.2.tgz",
+ "integrity": "sha512-7RNWbls5kAL1QVUOXvBsv1uO0wPQK3lHv+cY1gwkTzirnG1Nop4cBJZubpgziNbaVc/bl9QJcyvsf/NQxa3rjQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ts-error": "^1.0.6"
+ }
+ },
+ "node_modules/nice-grpc-opentelemetry": {
+ "version": "0.1.19",
+ "resolved": "https://registry.npmjs.org/nice-grpc-opentelemetry/-/nice-grpc-opentelemetry-0.1.19.tgz",
+ "integrity": "sha512-rjYVFbmSTE/g3XtxIh37PgEtE1ZOcwFoSHeLBCMRz9GAeGwZd23020QObgElF2UgU6kn1wpH8taWdprNr+3wfg==",
+ "license": "MIT",
+ "dependencies": {
+ "@opentelemetry/api": "^1.8.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0",
+ "abort-controller-x": "^0.4.0",
+ "ipaddr.js": "^2.0.1",
+ "nice-grpc-common": "^2.0.2"
+ }
+ },
+ "node_modules/nice-grpc-opentelemetry/node_modules/ipaddr.js": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
+ "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/nice-grpc-web": {
+ "version": "3.3.8",
+ "resolved": "https://registry.npmjs.org/nice-grpc-web/-/nice-grpc-web-3.3.8.tgz",
+ "integrity": "sha512-VOVzjcgl90lhoZgjXDg9hG8clIxe6NBk84R3p0P21CGitMesHMTV8g5adnDKQ4i60FJT1uk2EwepSyv1cND8JQ==",
+ "license": "MIT",
+ "dependencies": {
+ "abort-controller-x": "^0.4.0",
+ "isomorphic-ws": "^5.0.0",
+ "js-base64": "^3.7.2",
+ "nice-grpc-common": "^2.0.2"
+ }
+ },
+ "node_modules/nice-grpc/node_modules/@grpc/grpc-js": {
+ "version": "1.14.0",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.0.tgz",
+ "integrity": "sha512-N8Jx6PaYzcTRNzirReJCtADVoq4z7+1KQ4E70jTg/koQiMoUSN1kbNjPOqpPbhMFhfU1/l7ixspPl8dNY+FoUg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/proto-loader": "^0.8.0",
+ "@js-sdsl/ordered-map": "^4.4.2"
+ },
+ "engines": {
+ "node": ">=12.10.0"
+ }
+ },
+ "node_modules/nice-grpc/node_modules/@grpc/proto-loader": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz",
+ "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.5.3",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/nice-grpc/node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "license": "Apache-2.0"
+ },
"node_modules/no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
@@ -17501,10 +18484,11 @@
}
},
"node_modules/protobufjs": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
- "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz",
+ "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==",
"hasInstallScript": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"@protobufjs/aspromise": "^1.1.2",
"@protobufjs/base64": "^1.1.2",
@@ -18439,6 +19423,20 @@
"node": ">=0.10.0"
}
},
+ "node_modules/require-in-the-middle": {
+ "version": "7.5.2",
+ "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz",
+ "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.5",
+ "module-details-from-path": "^1.0.3",
+ "resolve": "^1.22.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
@@ -19558,6 +20556,17 @@
"node": ">=10.0.0"
}
},
+ "node_modules/streamx": {
+ "version": "2.23.0",
+ "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz",
+ "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==",
+ "license": "MIT",
+ "dependencies": {
+ "events-universal": "^1.0.0",
+ "fast-fifo": "^1.3.2",
+ "text-decoder": "^1.1.0"
+ }
+ },
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -19949,6 +20958,15 @@
"node": ">=8"
}
},
+ "node_modules/text-decoder": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz",
+ "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "b4a": "^1.6.4"
+ }
+ },
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -20108,6 +21126,12 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/ts-error": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/ts-error/-/ts-error-1.0.6.tgz",
+ "integrity": "sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==",
+ "license": "MIT"
+ },
"node_modules/ts-invariant": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz",
@@ -20119,6 +21143,39 @@
"node": ">=8"
}
},
+ "node_modules/ts-poet": {
+ "version": "6.12.0",
+ "resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-6.12.0.tgz",
+ "integrity": "sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "dprint-node": "^1.0.8"
+ }
+ },
+ "node_modules/ts-proto": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-2.8.1.tgz",
+ "integrity": "sha512-suKxr/MaDwCZhWPykXGIanxqFUE79zwN5SUKMCmVzyf32ZZeKSt2aut9kcx9DmXFocf2v1Jpr2ITWIQH4Xz+Bw==",
+ "license": "ISC",
+ "dependencies": {
+ "@bufbuild/protobuf": "^2.0.0",
+ "case-anything": "^2.1.13",
+ "ts-poet": "^6.12.0",
+ "ts-proto-descriptors": "2.0.0"
+ },
+ "bin": {
+ "protoc-gen-ts_proto": "protoc-gen-ts_proto"
+ }
+ },
+ "node_modules/ts-proto-descriptors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-2.0.0.tgz",
+ "integrity": "sha512-wHcTH3xIv11jxgkX5OyCSFfw27agpInAd6yh89hKG6zqIXnjW9SYqSER2CVQxdPj4czeOhGagNvZBEbJPy7qkw==",
+ "license": "ISC",
+ "dependencies": {
+ "@bufbuild/protobuf": "^2.0.0"
+ }
+ },
"node_modules/tsconfig-paths": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
@@ -21039,6 +22096,15 @@
"uuid": "dist/bin/uuid"
}
},
+ "node_modules/uuidv7": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/uuidv7/-/uuidv7-1.0.2.tgz",
+ "integrity": "sha512-8JQkH4ooXnm1JCIhqTMbtmdnYEn6oKukBxHn1Ic9878jMkL7daTI7anTExfY18VRCX7tcdn5quzvCb6EWrR8PA==",
+ "license": "Apache-2.0",
+ "bin": {
+ "uuidv7": "cli.js"
+ }
+ },
"node_modules/v8-to-istanbul": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz",
diff --git a/package.json b/package.json
index 82bb6dfde4..044eb5d4e3 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"@apollo/server": "^4.11.0",
"@as-integrations/next": "^3.1.0",
"@auth/prisma-adapter": "^2.7.0",
+ "@buildonspark/spark-sdk": "^0.4.2",
"@cashu/cashu-ts": "^2.4.1",
"@graphql-tools/schema": "^10.0.6",
"@lightninglabs/lnc-web": "^0.3.2-alpha",
@@ -36,6 +37,7 @@
"async-retry": "^1.3.3",
"aws-sdk": "^2.1691.0",
"bech32": "^2.0.0",
+ "bip39": "^3.1.0",
"bolt11": "^1.4.1",
"bootstrap": "^5.3.3",
"canonical-json": "0.0.4",
diff --git a/prisma/migrations/20250923052230_spark/migration.sql b/prisma/migrations/20250923052230_spark/migration.sql
new file mode 100644
index 0000000000..83f9b50de5
--- /dev/null
+++ b/prisma/migrations/20250923052230_spark/migration.sql
@@ -0,0 +1,68 @@
+-- AlterEnum
+ALTER TYPE "WalletName" ADD VALUE 'SPARK'; COMMIT;
+
+-- AlterEnum
+ALTER TYPE "WalletProtocolName" ADD VALUE 'SPARK'; COMMIT;
+
+-- AlterEnum
+ALTER TYPE "WalletSendProtocolName" ADD VALUE 'SPARK'; COMMIT;
+
+-- AlterEnum
+ALTER TYPE "WalletRecvProtocolName" ADD VALUE 'SPARK'; COMMIT;
+
+INSERT INTO "WalletTemplate" ("name", "sendProtocols", "recvProtocols")
+VALUES ('SPARK', '{SPARK}', '{SPARK}');
+
+-- CreateTable
+CREATE TABLE "WalletSendSpark" (
+ "id" SERIAL NOT NULL,
+ "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "protocolId" INTEGER NOT NULL,
+ "mnemonicVaultId" INTEGER NOT NULL,
+
+ CONSTRAINT "WalletSendSpark_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "WalletSendSpark_protocolId_key" ON "WalletSendSpark"("protocolId");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "WalletSendSpark_mnemonicVaultId_key" ON "WalletSendSpark"("mnemonicVaultId");
+
+-- AddForeignKey
+ALTER TABLE "WalletSendSpark" ADD CONSTRAINT "WalletSendSpark_protocolId_fkey" FOREIGN KEY ("protocolId") REFERENCES "WalletProtocol"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "WalletSendSpark" ADD CONSTRAINT "WalletSendSpark_mnemonicVaultId_fkey" FOREIGN KEY ("mnemonicVaultId") REFERENCES "Vault"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+CREATE TABLE "WalletRecvSpark" (
+ "id" SERIAL NOT NULL,
+ "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "protocolId" INTEGER NOT NULL,
+ "identityPublicKey" TEXT NOT NULL,
+
+ CONSTRAINT "WalletRecvSpark_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "WalletRecvSpark_protocolId_key" ON "WalletRecvSpark"("protocolId");
+
+-- AddForeignKey
+ALTER TABLE "WalletRecvSpark" ADD CONSTRAINT "WalletRecvSpark_protocolId_fkey" FOREIGN KEY ("protocolId") REFERENCES "WalletProtocol"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+CREATE TRIGGER wallet_to_jsonb
+ AFTER INSERT OR UPDATE ON "WalletSendSpark"
+ FOR EACH ROW
+ EXECUTE PROCEDURE wallet_to_jsonb();
+
+CREATE TRIGGER wallet_to_jsonb
+ AFTER INSERT OR UPDATE ON "WalletRecvSpark"
+ FOR EACH ROW
+ EXECUTE PROCEDURE wallet_to_jsonb();
+
+CREATE TRIGGER wallet_clear_vault
+ AFTER DELETE ON "WalletSendSpark"
+ FOR EACH ROW
+ EXECUTE PROCEDURE wallet_clear_vault();
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index c20511ffc2..6c54b9abc0 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -239,6 +239,7 @@ model Vault {
walletSendCLNRestRune WalletSendCLNRest? @relation("clnRune")
walletSendClink WalletSendClink? @relation("clinkNdebit")
walletSendClinkSecretKey WalletSendClink? @relation("clinkSecretKey")
+ walletSendSparkMnemonic WalletSendSpark? @relation("sparkMnemonic")
}
model WalletLog {
@@ -1233,6 +1234,7 @@ enum WalletProtocolName {
CLN_REST
LND_GRPC
CLINK
+ SPARK
}
enum WalletSendProtocolName {
@@ -1244,6 +1246,7 @@ enum WalletSendProtocolName {
LNC
CLN_REST
CLINK
+ SPARK
}
enum WalletRecvProtocolName {
@@ -1255,6 +1258,7 @@ enum WalletRecvProtocolName {
CLN_REST
LND_GRPC
CLINK
+ SPARK
}
enum WalletProtocolStatus {
@@ -1290,6 +1294,7 @@ enum WalletName {
LN_ADDR
CASH_APP
BLITZ
+ SPARK
}
model WalletTemplate {
@@ -1348,6 +1353,7 @@ model WalletProtocol {
walletSendLNC WalletSendLNC?
walletSendCLNRest WalletSendCLNRest?
walletSendClink WalletSendClink?
+ walletSendSpark WalletSendSpark?
walletRecvNWC WalletRecvNWC?
walletRecvLNbits WalletRecvLNbits?
@@ -1357,6 +1363,7 @@ model WalletProtocol {
walletRecvCLNRest WalletRecvCLNRest?
walletRecvLNDGRPC WalletRecvLNDGRPC?
walletRecvClink WalletRecvClink?
+ walletRecvSpark WalletRecvSpark?
@@unique(name: "WalletProtocol_walletId_send_name_key", [walletId, send, name])
@@index([walletId])
@@ -1453,6 +1460,16 @@ model WalletSendClink {
secretKey Vault? @relation("clinkSecretKey", fields: [secretKeyVaultId], references: [id])
}
+model WalletSendSpark {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now()) @map("created_at")
+ updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
+ protocolId Int @unique
+ protocol WalletProtocol @relation(fields: [protocolId], references: [id], onDelete: Cascade)
+ mnemonicVaultId Int @unique
+ mnemonic Vault? @relation("sparkMnemonic", fields: [mnemonicVaultId], references: [id])
+}
+
model WalletRecvNWC {
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @map("created_at")
@@ -1531,3 +1548,12 @@ model WalletRecvClink {
protocol WalletProtocol @relation(fields: [protocolId], references: [id], onDelete: Cascade)
noffer String
}
+
+model WalletRecvSpark {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now()) @map("created_at")
+ updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
+ protocolId Int @unique
+ protocol WalletProtocol @relation(fields: [protocolId], references: [id], onDelete: Cascade)
+ identityPublicKey String
+}
diff --git a/public/wallets/breez-dark.svg b/public/wallets/breez-dark.svg
new file mode 100644
index 0000000000..57ba8fcdc5
--- /dev/null
+++ b/public/wallets/breez-dark.svg
@@ -0,0 +1,10 @@
+
diff --git a/public/wallets/breez.svg b/public/wallets/breez.svg
new file mode 100644
index 0000000000..c7b98772a2
--- /dev/null
+++ b/public/wallets/breez.svg
@@ -0,0 +1,10 @@
+
diff --git a/public/wallets/spark-dark.svg b/public/wallets/spark-dark.svg
new file mode 100644
index 0000000000..302b527916
--- /dev/null
+++ b/public/wallets/spark-dark.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/public/wallets/spark.svg b/public/wallets/spark.svg
new file mode 100644
index 0000000000..80627e4ce3
--- /dev/null
+++ b/public/wallets/spark.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/wallets/client/components/form/hooks.js b/wallets/client/components/form/hooks.js
index 579ed176e8..9be529991a 100644
--- a/wallets/client/components/form/hooks.js
+++ b/wallets/client/components/form/hooks.js
@@ -84,8 +84,11 @@ function useProtocolFormState (protocol) {
export function useProtocolForm (protocol) {
const [formState, setFormState] = useProtocolFormState(protocol)
+
const [complementaryFormState] = useProtocolFormState({ name: protocol.name, send: !protocol.send })
const [nwcSendFormState] = useProtocolFormState({ name: 'NWC', send: true })
+ const [sparkFormState] = useProtocolFormState({ name: 'SPARK', send: true })
+
const wallet = useWallet()
const lud16Domain = walletLud16Domain(wallet.name)
const fields = protocolFields(protocol)
@@ -94,13 +97,17 @@ export function useProtocolForm (protocol) {
// after init, we use formState as the source of truth everywhere
let value = formState?.config?.[field.name] ?? protocol.config?.[field.name]
+ if (!value && field.initial) {
+ value = typeof field.initial === 'function' ? field.initial() : field.initial
+ }
+
if (!value && field.share) {
value = complementaryFormState?.config?.[field.name]
}
if (protocol.name === 'LN_ADDR' && field.name === 'address' && lud16Domain) {
- // automatically set lightning addresses from NWC urls if lud16 parameter is present
if (nwcSendFormState?.config?.url) {
+ // automatically set lightning addresses from NWC urls if lud16 parameter is present ...
const { lud16 } = parseNwcUrl(nwcSendFormState.config.url)
if (lud16?.split('@')[1] === lud16Domain) value = lud16
}
@@ -110,6 +117,12 @@ export function useProtocolForm (protocol) {
}
}
+ if (protocol.name === 'SPARK' && field.name === 'identityPublicKey') {
+ if (sparkFormState?.config?.identityPublicKey) {
+ value = sparkFormState.config.identityPublicKey
+ }
+ }
+
return {
...acc,
[field.name]: value || ''
diff --git a/wallets/client/components/form/index.js b/wallets/client/components/form/index.js
index 55dc93e974..53bfd9b38e 100644
--- a/wallets/client/components/form/index.js
+++ b/wallets/client/components/form/index.js
@@ -9,7 +9,7 @@ import Text from '@/components/text'
import Info from '@/components/info'
import { useFormState, useMaxSteps, useNext, useStepIndex } from '@/components/multi-step-form'
import { isTemplate, isWallet, protocolDisplayName, protocolFormId, protocolLogName, walletLud16Domain } from '@/wallets/lib/util'
-import { WalletGuide, WalletLayout, WalletLayoutHeader, WalletLayoutImageOrName, WalletLogs } from '@/wallets/client/components'
+import { WalletGuide, WalletLayout, WalletLayoutHeader, WalletLayoutImageOrName, WalletLayoutWarning, WalletLogs } from '@/wallets/client/components'
import { TemplateLogsProvider, useTestSendPayment, useWalletLogger, useTestCreateInvoice, useWalletSupport } from '@/wallets/client/hooks'
import ArrowRight from '@/svgs/arrow-right-s-fill.svg'
import { useFormikContext } from 'formik'
@@ -45,6 +45,7 @@ export function WalletMultiStepForm ({ wallet }) {
+
{steps.map(step => {
// WalletForm is aware of the current step via hooks
@@ -180,7 +181,7 @@ function WalletProtocolFormField ({ type, ...props }) {
const [protocol] = useProtocol()
const formik = useFormikContext()
- function transform ({ validate, encrypt, editable, help, share, ...props }) {
+ function transform ({ validate, encrypt, editable, help, share, initial, ...props }) {
const [upperHint, bottomHint] = Array.isArray(props.hint) ? props.hint : [null, props.hint]
const parseHelpText = text => Array.isArray(text) ? text.join('\n\n') : text
diff --git a/wallets/client/components/layout.js b/wallets/client/components/layout.js
index 0c08386095..72782381b4 100644
--- a/wallets/client/components/layout.js
+++ b/wallets/client/components/layout.js
@@ -1,8 +1,10 @@
+import { Alert } from 'react-bootstrap'
+import Link from 'next/link'
import Layout from '@/components/layout'
import { useWalletImage } from '@/wallets/client/hooks'
-import { walletDisplayName, walletGuideUrl } from '@/wallets/lib/util'
-import Link from 'next/link'
+import { walletDisplayName, walletGuideUrl, walletWarning } from '@/wallets/lib/util'
import InfoIcon from '@/svgs/information-fill.svg'
+import Text from '@/components/text'
export function WalletLayout ({ children }) {
// TODO(wallet-v2): py-5 doesn't work, I think it gets overriden by the layout class
@@ -69,3 +71,16 @@ export function WalletGuide ({ name }) {
)
}
+
+export function WalletLayoutWarning ({ name }) {
+ const warning = walletWarning(name)
+ if (!warning) return null
+
+ if (warning) {
+ return (
+
+ {warning}
+
+ )
+ }
+}
diff --git a/wallets/client/fragments/protocol.js b/wallets/client/fragments/protocol.js
index 6d2175e386..cbf4a3b955 100644
--- a/wallets/client/fragments/protocol.js
+++ b/wallets/client/fragments/protocol.js
@@ -265,6 +265,34 @@ export const UPSERT_WALLET_RECEIVE_CLINK = gql`
}
`
+export const UPSERT_WALLET_SEND_SPARK = gql`
+ mutation upsertWalletSendSpark(
+ ${shared.variables},
+ $mnemonic: VaultEntryInput!
+ ) {
+ upsertWalletSendSpark(
+ ${shared.arguments},
+ mnemonic: $mnemonic
+ ) {
+ id
+ }
+ }
+`
+
+export const UPSERT_WALLET_RECEIVE_SPARK = gql`
+ mutation upsertWalletRecvSpark(
+ ${shared.variables},
+ $identityPublicKey: String!
+ ) {
+ upsertWalletRecvSpark(
+ ${shared.arguments},
+ identityPublicKey: $identityPublicKey
+ ) {
+ id
+ }
+ }
+`
+
// tests
export const TEST_WALLET_RECEIVE_NWC = gql`
@@ -314,3 +342,9 @@ export const TEST_WALLET_RECEIVE_CLINK = gql`
testWalletRecvClink(noffer: $noffer)
}
`
+
+export const TEST_WALLET_RECEIVE_SPARK = gql`
+ mutation testWalletRecvSpark($identityPublicKey: String!) {
+ testWalletRecvSpark(identityPublicKey: $identityPublicKey)
+ }
+`
diff --git a/wallets/client/fragments/wallet.js b/wallets/client/fragments/wallet.js
index f018e1f549..f9d93a31fe 100644
--- a/wallets/client/fragments/wallet.js
+++ b/wallets/client/fragments/wallet.js
@@ -87,6 +87,12 @@ const WALLET_PROTOCOL_FIELDS = gql`
...VaultEntryFields
}
}
+ ... on WalletSendSpark {
+ id
+ encryptedMnemonic: mnemonic {
+ ...VaultEntryFields
+ }
+ }
... on WalletRecvNWC {
id
url
@@ -126,6 +132,10 @@ const WALLET_PROTOCOL_FIELDS = gql`
id
noffer
}
+ ... on WalletRecvSpark {
+ id
+ identityPublicKey
+ }
}
}
`
diff --git a/wallets/client/hooks/query.js b/wallets/client/hooks/query.js
index 83ece5eac1..aed96b44f3 100644
--- a/wallets/client/hooks/query.js
+++ b/wallets/client/hooks/query.js
@@ -21,6 +21,8 @@ import {
UPSERT_WALLET_SEND_WEBLN,
UPSERT_WALLET_SEND_CLN_REST,
UPSERT_WALLET_SEND_CLINK,
+ UPSERT_WALLET_SEND_SPARK,
+ UPSERT_WALLET_RECEIVE_SPARK,
WALLETS,
UPDATE_WALLET_ENCRYPTION,
RESET_WALLETS,
@@ -35,6 +37,7 @@ import {
TEST_WALLET_RECEIVE_CLN_REST,
TEST_WALLET_RECEIVE_LND_GRPC,
TEST_WALLET_RECEIVE_CLINK,
+ TEST_WALLET_RECEIVE_SPARK,
DELETE_WALLET
} from '@/wallets/client/fragments'
import { gql, useApolloClient, useMutation, useQuery } from '@apollo/client'
@@ -321,6 +324,8 @@ function protocolUpsertMutation (protocol) {
return protocol.send ? UPSERT_WALLET_SEND_WEBLN : NOOP_MUTATION
case 'CLINK':
return protocol.send ? UPSERT_WALLET_SEND_CLINK : UPSERT_WALLET_RECEIVE_CLINK
+ case 'SPARK':
+ return protocol.send ? UPSERT_WALLET_SEND_SPARK : UPSERT_WALLET_RECEIVE_SPARK
default:
return NOOP_MUTATION
}
@@ -346,6 +351,8 @@ function protocolTestMutation (protocol) {
return TEST_WALLET_RECEIVE_LND_GRPC
case 'CLINK':
return TEST_WALLET_RECEIVE_CLINK
+ case 'SPARK':
+ return TEST_WALLET_RECEIVE_SPARK
default:
return NOOP_MUTATION
}
diff --git a/wallets/client/protocols/index.js b/wallets/client/protocols/index.js
index 29efb9036c..0fe4fda2d9 100644
--- a/wallets/client/protocols/index.js
+++ b/wallets/client/protocols/index.js
@@ -6,6 +6,7 @@ import * as webln from './webln'
import * as lnc from './lnc'
import * as clnRest from './clnRest'
import * as clink from './clink'
+import * as spark from './spark'
export * from './util'
@@ -56,5 +57,6 @@ export default [
webln,
lnc,
clnRest,
- clink
+ clink,
+ spark
]
diff --git a/wallets/client/protocols/spark.js b/wallets/client/protocols/spark.js
new file mode 100644
index 0000000000..af341402b7
--- /dev/null
+++ b/wallets/client/protocols/spark.js
@@ -0,0 +1,42 @@
+import { withSparkWallet } from '@/wallets/lib/protocols/spark'
+import { sleep } from '@/lib/time'
+
+export const name = 'SPARK'
+
+const SPARK_PAYMENT_STATUS_POLL_INTERVAL_MS = 250
+
+export async function sendPayment (bolt11, { mnemonic }, { signal }) {
+ return await withSparkWallet(
+ mnemonic,
+ async wallet => {
+ // this can throw immediately, for example if invoice is from a different network
+ // or the wallet does have insufficient funds
+ const payment = await wallet.payLightningInvoice({ invoice: bolt11 })
+
+ // payments are async, we need to poll for status
+ while (!signal.aborted) {
+ const sendRequest = await wallet.getLightningSendRequest(payment.id)
+ if (sendRequest.paymentPreimage) {
+ return sendRequest.paymentPreimage
+ }
+ switch (sendRequest.status) {
+ case 'LIGHTNING_PAYMENT_FAILED':
+ // requests don't seem to include an error message:
+ // https://github.com/buildonspark/spark/blob/66f1cef206920745cec5df3b1e5339337fcf4b71/sdks/js/packages/spark-sdk/src/graphql/objects/LightningSendRequest.ts#L12-L48
+ throw new Error('Spark lightning send request failed')
+ case 'LIGHTNING_PAYMENT_PENDING':
+ default:
+ await sleep(SPARK_PAYMENT_STATUS_POLL_INTERVAL_MS)
+ }
+ }
+ }
+ )
+}
+
+export async function testSendPayment ({ mnemonic }, { signal }) {
+ const identityPublicKey = await withSparkWallet(
+ mnemonic,
+ wallet => wallet.getIdentityPublicKey()
+ )
+ return { identityPublicKey }
+}
diff --git a/wallets/lib/crypto.js b/wallets/lib/crypto.js
index e59b7fc99b..5e9b536de4 100644
--- a/wallets/lib/crypto.js
+++ b/wallets/lib/crypto.js
@@ -1,4 +1,5 @@
import bip39Words from '@/lib/bip39-words'
+import * as bip39 from 'bip39'
export async function deriveKey (passphrase, salt) {
const enc = new TextEncoder()
@@ -77,7 +78,5 @@ export async function decrypt (key, { iv, value }) {
}
export function generateRandomPassphrase () {
- const rand = new Uint32Array(12)
- window.crypto.getRandomValues(rand)
- return Array.from(rand).map(i => bip39Words[i % bip39Words.length]).join(' ')
+ return bip39.generateMnemonic(128, null, bip39Words)
}
diff --git a/wallets/lib/protocols/index.js b/wallets/lib/protocols/index.js
index f89a59af5e..8258af0e0f 100644
--- a/wallets/lib/protocols/index.js
+++ b/wallets/lib/protocols/index.js
@@ -8,10 +8,11 @@ import phoenixdSuite from './phoenixd'
import blinkSuite from './blink'
import webln from './webln'
import clinkSuite from './clink'
+import sparkSuite from './spark'
/**
* Protocol names as used in the database
- * @typedef {'NWC'|'LNBITS'|'PHOENIXD'|'BLINK'|'WEBLN'|'LN_ADDR'|'LNC'|'CLN_REST'|'LND_GRPC'|'CLINK'} ProtocolName
+ * @typedef {'NWC'|'LNBITS'|'PHOENIXD'|'BLINK'|'WEBLN'|'LN_ADDR'|'LNC'|'CLN_REST'|'LND_GRPC'|'CLINK'|'SPARK'} ProtocolName
* @typedef {'text'|'password'} InputType
*/
@@ -49,5 +50,6 @@ export default [
...lnbitsSuite,
...blinkSuite,
webln,
- ...clinkSuite
+ ...clinkSuite,
+ ...sparkSuite
]
diff --git a/wallets/lib/protocols/spark.js b/wallets/lib/protocols/spark.js
new file mode 100644
index 0000000000..4b24191071
--- /dev/null
+++ b/wallets/lib/protocols/spark.js
@@ -0,0 +1,60 @@
+import { bip39Validator, identityPublicKeyValidator } from '@/wallets/lib/validate'
+import { generateRandomPassphrase } from '@/wallets/lib/crypto'
+import { SparkWallet } from '@buildonspark/spark-sdk'
+
+// Spark
+// https://spark.money/
+// https://github.com/buildonspark/spark
+// https://docs.spark.money/api-reference
+
+export default [
+ {
+ name: 'SPARK',
+ send: true,
+ displayName: 'Spark',
+ fields: [
+ {
+ name: 'mnemonic',
+ label: 'mnemonic',
+ type: 'password',
+ required: true,
+ validate: bip39Validator(),
+ encrypt: true,
+ initial: generateRandomPassphrase,
+ disabled: true
+ }
+ ],
+ relationName: 'walletSendSpark'
+ },
+ {
+ name: 'SPARK',
+ send: false,
+ displayName: 'Spark',
+ fields: [
+ {
+ name: 'identityPublicKey',
+ label: 'identity public key',
+ type: 'password',
+ required: true,
+ validate: identityPublicKeyValidator()
+ }
+ ],
+ relationName: 'walletRecvSpark'
+ }
+]
+
+export async function withSparkWallet (mnemonic, cb) {
+ const { wallet } = await SparkWallet.initialize({
+ mnemonicOrSeed: mnemonic,
+ options: { network: 'MAINNET' }
+ })
+ try {
+ return await cb(wallet)
+ } finally {
+ await wallet.cleanupConnections()
+ }
+}
+
+export async function withRandomSparkWallet (cb) {
+ return await withSparkWallet(undefined, cb)
+}
diff --git a/wallets/lib/util.js b/wallets/lib/util.js
index 2a43e0963c..b58ea36093 100644
--- a/wallets/lib/util.js
+++ b/wallets/lib/util.js
@@ -11,6 +11,14 @@ export function walletDisplayName (name) {
return walletJson(name)?.displayName || titleCase(name)
}
+export function walletWarning (name) {
+ let { warning } = walletJson(name)
+ if (Array.isArray(warning)) {
+ warning = warning.join('\n')
+ }
+ return warning
+}
+
export function walletImage (name) {
return walletJson(name)?.image
}
diff --git a/wallets/lib/validate.js b/wallets/lib/validate.js
index 9c3945749d..4b8d2e52fd 100644
--- a/wallets/lib/validate.js
+++ b/wallets/lib/validate.js
@@ -1,4 +1,5 @@
import bip39Words from '@/lib/bip39-words'
+import * as bip39 from 'bip39'
import { decodeRune } from '@/lib/cln'
import { B64_URL_REGEX } from '@/lib/format'
import { isInvoicableMacaroon, isInvoiceMacaroon } from '@/lib/macaroon'
@@ -147,6 +148,12 @@ export const bip39Validator = ({ min = 12, max = 24 } = {}) =>
.test({
name: 'bip39',
test: async (value, context) => {
+ // legacy mnemonics don't include a checksum so if validation with the
+ // bip39 library fails we assume it's an old mnemonic and use legacy validation
+ if (bip39.validateMnemonic(value, bip39Words)) {
+ return true
+ }
+
const words = value ? value.trim().split(/[\s]+/) : []
for (const w of words) {
try {
@@ -198,3 +205,19 @@ export const urlValidator = (...args) =>
})
export const hexValidator = (length) => string().hex().length(length, `must be exactly ${length} hex chars`)
+
+export const identityPublicKeyValidator = () => string()
+ .test({
+ name: 'identityPublicKey',
+ test: (identityPublicKey, context) => {
+ try {
+ if (!identityPublicKey.startsWith('02') && !identityPublicKey.startsWith('03')) {
+ throw new Error('must start with 02 or 03')
+ }
+ hexValidator(64).validateSync(identityPublicKey.slice(2))
+ } catch (err) {
+ return context.createError({ message: err.message })
+ }
+ return true
+ }
+ })
diff --git a/wallets/lib/wallets.json b/wallets/lib/wallets.json
index 1975a9d26b..a2637f79fa 100644
--- a/wallets/lib/wallets.json
+++ b/wallets/lib/wallets.json
@@ -168,5 +168,15 @@
"displayName": "Blitz Wallet",
"image": "/wallets/blitz.png",
"url": "https://blitz-wallet.com/"
+ },
+ {
+ "name": "SPARK",
+ "displayName": "Spark",
+ "image": "/wallets/spark.svg",
+ "url": "https://spark.money/",
+ "warning": [
+ "**Spark balances are public.**",
+ "Anyone with your identity public key can look up your balance on [www.sparkscan.io](https://www.sparkscan.io/)."
+ ]
}
]
diff --git a/wallets/server/protocols/index.js b/wallets/server/protocols/index.js
index 6bf8ca043b..6151e217d0 100644
--- a/wallets/server/protocols/index.js
+++ b/wallets/server/protocols/index.js
@@ -6,6 +6,7 @@ import * as phoenixd from './phoenixd'
import * as blink from './blink'
import * as lndGrpc from './lndGrpc'
import * as clink from './clink'
+import * as spark from './spark'
export * from './util'
@@ -58,5 +59,6 @@ export default [
phoenixd,
blink,
lndGrpc,
- clink
+ clink,
+ spark
]
diff --git a/wallets/server/protocols/spark.js b/wallets/server/protocols/spark.js
new file mode 100644
index 0000000000..5c690972ca
--- /dev/null
+++ b/wallets/server/protocols/spark.js
@@ -0,0 +1,21 @@
+import { msatsToSats } from '@/lib/format'
+import { withRandomSparkWallet } from '@/wallets/lib/protocols/spark'
+
+export const name = 'SPARK'
+
+export async function createInvoice ({ msats, description }, { identityPublicKey }, { signal }) {
+ return await withRandomSparkWallet(
+ async wallet => {
+ const { invoice: { encodedInvoice: bolt11 } } = await wallet.createLightningInvoice({
+ amountSats: msatsToSats(msats),
+ memo: description,
+ receiverIdentityPubkey: identityPublicKey
+ })
+ return bolt11
+ }
+ )
+}
+
+export async function testCreateInvoice ({ identityPublicKey }, { signal }) {
+ return await createInvoice({ msats: 1000, description: 'SN test invoice' }, { identityPublicKey }, { signal })
+}
diff --git a/wallets/server/resolvers/util.js b/wallets/server/resolvers/util.js
index 5553ef4dfe..ffa7e921f3 100644
--- a/wallets/server/resolvers/util.js
+++ b/wallets/server/resolvers/util.js
@@ -21,6 +21,8 @@ export function mapWalletResolveTypes (wallet) {
return 'WalletRecvLNDGRPC'
case 'CLINK':
return send ? 'WalletSendClink' : 'WalletRecvClink'
+ case 'SPARK':
+ return send ? 'WalletSendSpark' : 'WalletRecvSpark'
default:
return null
}