CLINK offers (#2518)
This commit is contained in:
parent
3df155f4f1
commit
94177af702
@ -108,6 +108,11 @@ const typeDefs = gql`
|
||||
${shared}
|
||||
): WalletSendWebLN!
|
||||
|
||||
upsertWalletRecvClink(
|
||||
${shared},
|
||||
noffer: String!
|
||||
): WalletRecvClink!
|
||||
|
||||
# tests
|
||||
testWalletRecvNWC(
|
||||
url: String!
|
||||
@ -144,6 +149,10 @@ const typeDefs = gql`
|
||||
apiKey: String!
|
||||
): Boolean!
|
||||
|
||||
testWalletRecvClink(
|
||||
noffer: String!
|
||||
): Boolean!
|
||||
|
||||
# delete
|
||||
deleteWallet(id: ID!): Boolean
|
||||
|
||||
@ -226,6 +235,7 @@ const typeDefs = gql`
|
||||
| WalletRecvLightningAddress
|
||||
| WalletRecvCLNRest
|
||||
| WalletRecvLNDGRPC
|
||||
| WalletRecvClink
|
||||
|
||||
type WalletSettings {
|
||||
receiveCreditsBelowSats: Int!
|
||||
@ -328,6 +338,11 @@ const typeDefs = gql`
|
||||
cert: String
|
||||
}
|
||||
|
||||
type WalletRecvClink {
|
||||
id: ID!
|
||||
noffer: String!
|
||||
}
|
||||
|
||||
input AutowithdrawSettings {
|
||||
autoWithdrawThreshold: Int!
|
||||
autoWithdrawMaxFeePercent: Float!
|
||||
|
@ -843,6 +843,27 @@ services:
|
||||
CONNECT: "localhost:${LNBITS_WEB_PORT_V1}"
|
||||
TORDIR: "/app/.tor"
|
||||
cpu_shares: "${CPU_SHARES_LOW}"
|
||||
lnpub:
|
||||
image: ghcr.io/shocknet/lightning-pub@sha256:cd7bb9298d09a2cdaf1b6456ef6154e3ba24f7b902ad29cda2c08c2a4fa2af6e
|
||||
container_name: lnpub
|
||||
profiles:
|
||||
- wallets
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- lnpub:/app/data
|
||||
- lnd:/app/.lnd
|
||||
environment:
|
||||
- LND_ADDRESS=lnd:10009
|
||||
- LND_CERT_PATH=/app/.lnd/tls.cert
|
||||
- LND_MACAROON_PATH=/app/.lnd/data/chain/bitcoin/regtest/admin.macaroon
|
||||
ports:
|
||||
- ${LNPUB_PORT_1776:-1776}:1776
|
||||
- ${LNPUB_PORT_1777:-1777}:1777
|
||||
depends_on:
|
||||
lnd:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
cpu_shares: "${CPU_SHARES_LOW}"
|
||||
dnsmasq:
|
||||
image: 4km3/dnsmasq:2.90-r3
|
||||
profiles:
|
||||
@ -879,6 +900,7 @@ volumes:
|
||||
tordata:
|
||||
eclair:
|
||||
dnsmasq:
|
||||
lnpub:
|
||||
|
||||
networks:
|
||||
default: {}
|
||||
|
228
package-lock.json
generated
228
package-lock.json
generated
@ -20,6 +20,7 @@
|
||||
"@nostr-dev-kit/ndk-wallet": "^0.5.0",
|
||||
"@opensearch-project/opensearch": "^2.12.0",
|
||||
"@prisma/client": "^5.20.0",
|
||||
"@shocknet/clink-sdk": "^1.4.0",
|
||||
"@slack/web-api": "^7.6.0",
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@yudiel/react-qr-scanner": "^2.0.8",
|
||||
@ -3236,11 +3237,31 @@
|
||||
"url": "https://github.com/sponsors/nzakas"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/balanced-match": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
||||
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/brace-expansion": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
|
||||
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@isaacs/balanced-match": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"string-width": "^5.1.2",
|
||||
"string-width-cjs": "npm:string-width@^4.2.0",
|
||||
@ -3257,7 +3278,6 @@
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@ -3269,7 +3289,6 @@
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@ -3280,14 +3299,12 @@
|
||||
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/string-width": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"eastasianwidth": "^0.2.0",
|
||||
"emoji-regex": "^9.2.2",
|
||||
@ -3304,7 +3321,6 @@
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
@ -3319,7 +3335,6 @@
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.1.0",
|
||||
"string-width": "^5.0.1",
|
||||
@ -5269,6 +5284,137 @@
|
||||
"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",
|
||||
"integrity": "sha512-J0PWE8CVRJrFF1Zi/UhChhvOrlmDj7LRJTpR6rbHlFPmjC5TGIW6891tVWWv+JmUR0jzez9QHFrHnc8DgIJYCQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.8.0",
|
||||
"@scure/base": "^1.2.5",
|
||||
"nostr-tools": "^2.13.0",
|
||||
"rimraf": "^6.0.1",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@shocknet/clink-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/@shocknet/clink-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/@shocknet/clink-sdk/node_modules/glob": {
|
||||
"version": "11.0.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
|
||||
"integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.3.1",
|
||||
"jackspeak": "^4.1.1",
|
||||
"minimatch": "^10.0.3",
|
||||
"minipass": "^7.1.2",
|
||||
"package-json-from-dist": "^1.0.0",
|
||||
"path-scurry": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@shocknet/clink-sdk/node_modules/jackspeak": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
|
||||
"integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@shocknet/clink-sdk/node_modules/lru-cache": {
|
||||
"version": "11.2.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.1.tgz",
|
||||
"integrity": "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@shocknet/clink-sdk/node_modules/minimatch": {
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
|
||||
"integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@isaacs/brace-expansion": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@shocknet/clink-sdk/node_modules/path-scurry": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
|
||||
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^11.0.0",
|
||||
"minipass": "^7.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@shocknet/clink-sdk/node_modules/rimraf": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz",
|
||||
"integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^11.0.0",
|
||||
"package-json-from-dist": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@sinclair/typebox": {
|
||||
"version": "0.27.8",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
||||
@ -8308,10 +8454,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dev": true,
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
@ -8993,8 +9139,7 @@
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
|
||||
},
|
||||
"node_modules/ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
@ -10466,12 +10611,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
|
||||
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
|
||||
"dev": true,
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
||||
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"cross-spawn": "^7.0.6",
|
||||
"signal-exit": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
@ -10485,7 +10630,6 @@
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
@ -12082,8 +12226,7 @@
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
||||
},
|
||||
"node_modules/isomorphic-ws": {
|
||||
"version": "5.0.0",
|
||||
@ -15874,7 +16017,6 @@
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
@ -16157,19 +16299,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nostr-tools": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.8.0.tgz",
|
||||
"integrity": "sha512-aumZBa9Ok/cAJLovSBCIA/DkJjLjF/Hs5DpQGEjmyfaUkGBqd5jZjzalcVMyy/9HkkRZfJmbTPtqHTKFNvBSHQ==",
|
||||
"version": "2.16.2",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.16.2.tgz",
|
||||
"integrity": "sha512-ZxH9EbSt5ypURZj2TGNJxZd0Omb5ag5KZSu8IyJMCdLyg2KKz+2GA0sP/cSawCQEkyviIN4eRT4G2gB/t9lMRw==",
|
||||
"license": "Unlicense",
|
||||
"dependencies": {
|
||||
"@noble/ciphers": "^0.5.1",
|
||||
"@noble/curves": "1.2.0",
|
||||
"@noble/hashes": "1.3.1",
|
||||
"@scure/base": "1.1.1",
|
||||
"@scure/bip32": "1.3.1",
|
||||
"@scure/bip39": "1.2.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"nostr-wasm": "v0.1.0"
|
||||
"@scure/bip39": "1.2.1",
|
||||
"nostr-wasm": "0.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=5.0.0"
|
||||
@ -16205,8 +16346,7 @@
|
||||
"node_modules/nostr-wasm": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.1.0.tgz",
|
||||
"integrity": "sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==",
|
||||
"optional": true
|
||||
"integrity": "sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA=="
|
||||
},
|
||||
"node_modules/npm-run-path": {
|
||||
"version": "4.0.1",
|
||||
@ -16586,6 +16726,12 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/package-json-from-dist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
|
||||
"license": "BlueOak-1.0.0"
|
||||
},
|
||||
"node_modules/packet-reader": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
|
||||
@ -16681,7 +16827,6 @@
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@ -18699,7 +18844,6 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
},
|
||||
@ -18711,7 +18855,6 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@ -19368,7 +19511,6 @@
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
@ -19488,7 +19630,6 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
@ -20320,9 +20461,9 @@
|
||||
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g=="
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
|
||||
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
|
||||
"version": "5.9.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
|
||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
@ -21185,7 +21326,6 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
@ -21538,7 +21678,6 @@
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
@ -21555,7 +21694,6 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
@ -21570,7 +21708,6 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
@ -21581,8 +21718,7 @@
|
||||
"node_modules/wrap-ansi-cjs/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
|
@ -25,6 +25,7 @@
|
||||
"@nostr-dev-kit/ndk-wallet": "^0.5.0",
|
||||
"@opensearch-project/opensearch": "^2.12.0",
|
||||
"@prisma/client": "^5.20.0",
|
||||
"@shocknet/clink-sdk": "^1.4.0",
|
||||
"@slack/web-api": "^7.6.0",
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@yudiel/react-qr-scanner": "^2.0.8",
|
||||
|
31
prisma/migrations/20250905014333_clink_recv/migration.sql
Normal file
31
prisma/migrations/20250905014333_clink_recv/migration.sql
Normal file
@ -0,0 +1,31 @@
|
||||
-- AlterEnum
|
||||
ALTER TYPE "WalletProtocolName" ADD VALUE 'CLINK'; COMMIT;
|
||||
|
||||
-- AlterEnum
|
||||
ALTER TYPE "WalletRecvProtocolName" ADD VALUE 'CLINK'; COMMIT;
|
||||
|
||||
UPDATE "WalletTemplate"
|
||||
SET "recvProtocols" = array_prepend('CLINK', "recvProtocols")
|
||||
WHERE "name" = 'SHOCKWALLET';
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "WalletRecvClink" (
|
||||
"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,
|
||||
"noffer" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "WalletRecvClink_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "WalletRecvClink_protocolId_key" ON "WalletRecvClink"("protocolId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "WalletRecvClink" ADD CONSTRAINT "WalletRecvClink_protocolId_fkey" FOREIGN KEY ("protocolId") REFERENCES "WalletProtocol"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
CREATE TRIGGER wallet_to_jsonb
|
||||
AFTER INSERT OR UPDATE ON "WalletRecvClink"
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE wallet_to_jsonb();
|
@ -1213,6 +1213,7 @@ enum WalletProtocolName {
|
||||
LNC
|
||||
CLN_REST
|
||||
LND_GRPC
|
||||
CLINK
|
||||
}
|
||||
|
||||
enum WalletSendProtocolName {
|
||||
@ -1233,6 +1234,7 @@ enum WalletRecvProtocolName {
|
||||
LN_ADDR
|
||||
CLN_REST
|
||||
LND_GRPC
|
||||
CLINK
|
||||
}
|
||||
|
||||
enum WalletProtocolStatus {
|
||||
@ -1333,6 +1335,7 @@ model WalletProtocol {
|
||||
walletRecvLightningAddress WalletRecvLightningAddress?
|
||||
walletRecvCLNRest WalletRecvCLNRest?
|
||||
walletRecvLNDGRPC WalletRecvLNDGRPC?
|
||||
walletRecvClink WalletRecvClink?
|
||||
|
||||
@@unique(name: "WalletProtocol_walletId_send_name_key", [walletId, send, name])
|
||||
@@index([walletId])
|
||||
@ -1486,3 +1489,12 @@ model WalletRecvLNDGRPC {
|
||||
macaroon String
|
||||
cert String?
|
||||
}
|
||||
|
||||
model WalletRecvClink {
|
||||
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)
|
||||
noffer String
|
||||
}
|
||||
|
@ -235,6 +235,20 @@ export const UPSERT_WALLET_SEND_WEBLN = gql`
|
||||
}
|
||||
`
|
||||
|
||||
export const UPSERT_WALLET_RECEIVE_CLINK = gql`
|
||||
mutation upsertWalletRecvClink(
|
||||
${shared.variables},
|
||||
$noffer: String!
|
||||
) {
|
||||
upsertWalletRecvClink(
|
||||
${shared.arguments},
|
||||
noffer: $noffer
|
||||
) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// tests
|
||||
|
||||
export const TEST_WALLET_RECEIVE_NWC = gql`
|
||||
@ -278,3 +292,9 @@ export const TEST_WALLET_RECEIVE_BLINK = gql`
|
||||
testWalletRecvBlink(currency: $currency, apiKey: $apiKey)
|
||||
}
|
||||
`
|
||||
|
||||
export const TEST_WALLET_RECEIVE_CLINK = gql`
|
||||
mutation testWalletRecvClink($noffer: String!) {
|
||||
testWalletRecvClink(noffer: $noffer)
|
||||
}
|
||||
`
|
||||
|
@ -113,6 +113,10 @@ const WALLET_PROTOCOL_FIELDS = gql`
|
||||
macaroon
|
||||
cert
|
||||
}
|
||||
... on WalletRecvClink {
|
||||
id
|
||||
noffer
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
UPSERT_WALLET_RECEIVE_LND_GRPC,
|
||||
UPSERT_WALLET_RECEIVE_NWC,
|
||||
UPSERT_WALLET_RECEIVE_PHOENIXD,
|
||||
UPSERT_WALLET_RECEIVE_CLINK,
|
||||
UPSERT_WALLET_SEND_BLINK,
|
||||
UPSERT_WALLET_SEND_LNBITS,
|
||||
UPSERT_WALLET_SEND_LNC,
|
||||
@ -26,6 +27,7 @@ import {
|
||||
TEST_WALLET_RECEIVE_NWC,
|
||||
TEST_WALLET_RECEIVE_CLN_REST,
|
||||
TEST_WALLET_RECEIVE_LND_GRPC,
|
||||
TEST_WALLET_RECEIVE_CLINK,
|
||||
DELETE_WALLET
|
||||
} from '@/wallets/client/fragments'
|
||||
import { gql, useApolloClient, useMutation, useQuery } from '@apollo/client'
|
||||
@ -315,6 +317,8 @@ function protocolUpsertMutation (protocol) {
|
||||
return protocol.send ? UPSERT_WALLET_SEND_LNC : NOOP_MUTATION
|
||||
case 'WEBLN':
|
||||
return protocol.send ? UPSERT_WALLET_SEND_WEBLN : NOOP_MUTATION
|
||||
case 'CLINK':
|
||||
return protocol.send ? NOOP_MUTATION : UPSERT_WALLET_RECEIVE_CLINK
|
||||
default:
|
||||
return NOOP_MUTATION
|
||||
}
|
||||
@ -338,6 +342,8 @@ function protocolTestMutation (protocol) {
|
||||
return TEST_WALLET_RECEIVE_CLN_REST
|
||||
case 'LND_GRPC':
|
||||
return TEST_WALLET_RECEIVE_LND_GRPC
|
||||
case 'CLINK':
|
||||
return TEST_WALLET_RECEIVE_CLINK
|
||||
default:
|
||||
return NOOP_MUTATION
|
||||
}
|
||||
|
21
wallets/lib/protocols/clink.js
Normal file
21
wallets/lib/protocols/clink.js
Normal file
@ -0,0 +1,21 @@
|
||||
import { clinkValidator } from '@/wallets/lib/validate'
|
||||
|
||||
// CLINK: Common Lightning Interface for Nostr Keys
|
||||
// https://github.com/shocknet/CLINK/
|
||||
|
||||
export default {
|
||||
name: 'CLINK',
|
||||
displayName: 'CLINK',
|
||||
send: false,
|
||||
fields: [
|
||||
{
|
||||
name: 'noffer',
|
||||
label: 'noffer',
|
||||
type: 'password',
|
||||
placeholder: 'noffer...',
|
||||
required: true,
|
||||
validate: clinkValidator('noffer')
|
||||
}
|
||||
],
|
||||
relationName: 'walletRecvClink'
|
||||
}
|
17
wallets/lib/protocols/docs/dev/clink.md
Normal file
17
wallets/lib/protocols/docs/dev/clink.md
Normal file
@ -0,0 +1,17 @@
|
||||
Testing CLINK is done with Lightning.Pub and Shockwallet.
|
||||
|
||||
Shockwallet PWA: https://my.shockwallet.app/
|
||||
|
||||
Steps:
|
||||
|
||||
1. Run this command to get `nprofile` of the lnpub container
|
||||
|
||||
```
|
||||
$ sndev logs --since 0 lnpub | grep -oE 'nprofile1\w+'
|
||||
```
|
||||
|
||||
2. Go to https://my.shockwallet.app/sources
|
||||
3. Add a new source and paste `nprofile`
|
||||
4. Go to https://my.shockwallet.app/offers
|
||||
5. Reload page to make sure the offer is correctly updated
|
||||
6. Copy offer and paste into SN
|
@ -7,6 +7,7 @@ import lnbitsSuite from './lnbits'
|
||||
import phoenixdSuite from './phoenixd'
|
||||
import blinkSuite from './blink'
|
||||
import webln from './webln'
|
||||
import clink from './clink'
|
||||
|
||||
/**
|
||||
* Protocol names as used in the database
|
||||
@ -45,5 +46,6 @@ export default [
|
||||
...phoenixdSuite,
|
||||
...lnbitsSuite,
|
||||
...blinkSuite,
|
||||
webln
|
||||
webln,
|
||||
clink
|
||||
]
|
||||
|
@ -5,6 +5,7 @@ import { isInvoicableMacaroon, isInvoiceMacaroon } from '@/lib/macaroon'
|
||||
import { NOSTR_PUBKEY_HEX } from '@/lib/nostr'
|
||||
import { TOR_REGEXP } from '@/lib/url'
|
||||
import { lightningAddressValidator } from '@/lib/validate'
|
||||
import { decodeBech32 as clinkDecodeBech32, OfferPriceType } from '@shocknet/clink-sdk'
|
||||
import { string, array } from 'yup'
|
||||
|
||||
export const externalLightningAddressValidator = lightningAddressValidator
|
||||
@ -65,6 +66,35 @@ export function parseNwcUrl (walletConnectUrl) {
|
||||
}
|
||||
}
|
||||
|
||||
export const clinkValidator = (type) =>
|
||||
string()
|
||||
.matches(new RegExp(`^${type}1`), { message: `must start with ${type}1` })
|
||||
.matches(/^(noffer|ndebit)1[02-9ac-hj-np-z]+$/, { message: 'invalid bech32 encoding' })
|
||||
.test({
|
||||
name: 'decode',
|
||||
test: (v, context) => {
|
||||
let decoded
|
||||
try {
|
||||
decoded = clinkDecodeBech32(v)
|
||||
} catch (e) {
|
||||
return context.createError({ message: `failed to decode bech32: ${e.message}` })
|
||||
}
|
||||
|
||||
if (decoded.type !== type) {
|
||||
return context.createError({ message: `must be ${type}` })
|
||||
}
|
||||
|
||||
const { data } = decoded
|
||||
if (!data) return context.createError({ message: 'no data' })
|
||||
|
||||
if (type === 'noffer' && data.priceType && data.priceType !== OfferPriceType.Spontaneous) {
|
||||
return context.createError({ message: 'offer must be for spontaneous payments' })
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
export const socketValidator = (msg = 'invalid socket') =>
|
||||
string()
|
||||
.test({
|
||||
|
49
wallets/server/protocols/clink.js
Normal file
49
wallets/server/protocols/clink.js
Normal file
@ -0,0 +1,49 @@
|
||||
import { WALLET_CREATE_INVOICE_TIMEOUT_MS } from '@/lib/constants'
|
||||
import { msatsToSats } from '@/lib/format'
|
||||
import { decodeBech32, generateSecretKey, SendNofferRequest, SimplePool } from '@shocknet/clink-sdk'
|
||||
|
||||
export const name = 'CLINK'
|
||||
|
||||
// https://clinkme.dev/specs.html
|
||||
const ERR_INVALID_AMOUNT = 5
|
||||
|
||||
export async function createInvoice (
|
||||
{ msats, description, expiry },
|
||||
{ noffer },
|
||||
{ signal }) {
|
||||
const { data: { offer, relay, pubkey } } = decodeBech32(noffer)
|
||||
|
||||
const pool = new SimplePool()
|
||||
const sk = generateSecretKey()
|
||||
const request = { offer, amount_sats: msatsToSats(msats), expires_in_seconds: expiry, description }
|
||||
|
||||
let response
|
||||
try {
|
||||
const timeout = Math.floor(WALLET_CREATE_INVOICE_TIMEOUT_MS / 1000)
|
||||
// CLINK does not support a custom invoice description or expiry
|
||||
response = await SendNofferRequest(pool, sk, [relay], pubkey, request, timeout)
|
||||
} catch (e) {
|
||||
throw typeof e === 'string' ? new Error(e) : e
|
||||
} finally {
|
||||
pool.close([relay])
|
||||
}
|
||||
|
||||
if ('bolt11' in response && typeof response.bolt11 === 'string') {
|
||||
return response.bolt11
|
||||
}
|
||||
|
||||
if (response.code === ERR_INVALID_AMOUNT) {
|
||||
const { min, max } = response.range
|
||||
throw new Error(`invalid amount: amount must be between ${min} and ${max} sats`)
|
||||
}
|
||||
|
||||
throw new Error(response.error)
|
||||
}
|
||||
|
||||
export async function testCreateInvoice ({ noffer }, { signal }) {
|
||||
return await createInvoice(
|
||||
// lnpub minimum range seems to be 10 sats by default so we use 100 sats
|
||||
{ msats: 100e3, description: 'SN test invoice', expiry: 1 },
|
||||
{ noffer },
|
||||
{ signal })
|
||||
}
|
@ -5,6 +5,7 @@ import * as clnRest from './clnRest'
|
||||
import * as phoenixd from './phoenixd'
|
||||
import * as blink from './blink'
|
||||
import * as lndGrpc from './lndGrpc'
|
||||
import * as clink from './clink'
|
||||
|
||||
export * from './util'
|
||||
|
||||
@ -56,5 +57,6 @@ export default [
|
||||
clnRest,
|
||||
phoenixd,
|
||||
blink,
|
||||
lndGrpc
|
||||
lndGrpc,
|
||||
clink
|
||||
]
|
||||
|
@ -19,6 +19,8 @@ export function mapWalletResolveTypes (wallet) {
|
||||
return send ? 'WalletSendCLNRest' : 'WalletRecvCLNRest'
|
||||
case 'LND_GRPC':
|
||||
return 'WalletRecvLNDGRPC'
|
||||
case 'CLINK':
|
||||
return 'WalletRecvClink'
|
||||
default:
|
||||
return null
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user