mirror of
https://github.com/Permissionless-Software-Foundation/psf-bch-api-base.git
synced 2026-09-21 16:52:00 -07:00
Finished implementation
This commit is contained in:
+3
-6
@@ -22,15 +22,12 @@ export LOCAL_RESTURL=http://localhost:5942/v6
|
|||||||
export PORT=5942
|
export PORT=5942
|
||||||
|
|
||||||
# x402 payments required to access this API?
|
# x402 payments required to access this API?
|
||||||
# Facilitators https://docs.cdp.coinbase.com/x402/quickstart-for-sellers
|
|
||||||
export X402_ENABLED=true
|
export X402_ENABLED=true
|
||||||
export SERVER_BASE_ADDRESS=0xd32585CE60815654C50CAf350e18de8096061e63
|
export SERVER_BASE_ADDRESS=0xd32585CE60815654C50CAf350e18de8096061e63
|
||||||
export FACILITATOR_URL=https://x402.org/facilitator #Testnet Facilitator
|
export X402_PRICE_USDC=0.1
|
||||||
export X402_PRICE_USDC=0.01
|
export x402_NETWORK=base
|
||||||
|
export x402_FACILITATOR_URL=http://localhost:4022
|
||||||
|
|
||||||
# Mainnet facilitator access keys
|
|
||||||
export FACILITATOR_KEY_ID=
|
|
||||||
export FACILITATOR_SECRET_KEY=
|
|
||||||
|
|
||||||
# Basic Authentication required to access this API?
|
# Basic Authentication required to access this API?
|
||||||
export USE_BASIC_AUTH=true
|
export USE_BASIC_AUTH=true
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export EVM_PRIVATE_KEY=
|
||||||
|
export NETWORK=base
|
||||||
|
|
||||||
|
node facilitator-server.js
|
||||||
@@ -4,3 +4,4 @@ logs/
|
|||||||
docs/
|
docs/
|
||||||
coverage/
|
coverage/
|
||||||
start.sh
|
start.sh
|
||||||
|
start-facilitator.sh
|
||||||
|
|||||||
+4
-9
@@ -16,7 +16,7 @@ import { dirname, join } from 'path'
|
|||||||
import config from '../src/config/index.js'
|
import config from '../src/config/index.js'
|
||||||
import Controllers from '../src/controllers/index.js'
|
import Controllers from '../src/controllers/index.js'
|
||||||
import wlogger from '../src/adapters/wlogger.js'
|
import wlogger from '../src/adapters/wlogger.js'
|
||||||
import { buildX402Routes, getX402Settings, getBasicAuthSettings } from '../src/config/x402.js'
|
import { buildX402Routes, getX402Settings, getBasicAuthSettings, createAuthHeader } from '../src/config/x402.js'
|
||||||
import { basicAuthMiddleware } from '../src/middleware/basic-auth.js'
|
import { basicAuthMiddleware } from '../src/middleware/basic-auth.js'
|
||||||
|
|
||||||
// Load environment variables
|
// Load environment variables
|
||||||
@@ -111,10 +111,7 @@ class Server {
|
|||||||
if (facilitatorOptions) {
|
if (facilitatorOptions) {
|
||||||
facilitatorOptions = {
|
facilitatorOptions = {
|
||||||
url: x402Settings.facilitatorUrl,
|
url: x402Settings.facilitatorUrl,
|
||||||
/** TODO : Auth headers for request mainnet facilitator needed */
|
createAuthHeaders: createAuthHeader
|
||||||
createAuthHeaders: async () => {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,6 +119,7 @@ class Server {
|
|||||||
|
|
||||||
// Create conditional x402 middleware that bypasses if basic auth is valid
|
// Create conditional x402 middleware that bypasses if basic auth is valid
|
||||||
const conditionalX402Middleware = (req, res, next) => {
|
const conditionalX402Middleware = (req, res, next) => {
|
||||||
|
// req.headers['accept'] = 'application/json';
|
||||||
// If basic auth is valid, bypass x402
|
// If basic auth is valid, bypass x402
|
||||||
if (req.locals?.basicAuthValid === true) {
|
if (req.locals?.basicAuthValid === true) {
|
||||||
return next()
|
return next()
|
||||||
@@ -144,10 +142,7 @@ class Server {
|
|||||||
if (facilitatorOptions) {
|
if (facilitatorOptions) {
|
||||||
facilitatorOptions = {
|
facilitatorOptions = {
|
||||||
url: x402Settings.facilitatorUrl,
|
url: x402Settings.facilitatorUrl,
|
||||||
/** TODO : Auth headers for request mainnet facilitator needed */
|
createAuthHeaders: createAuthHeader
|
||||||
createAuthHeaders: async () => {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,32 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { withPaymentInterceptor } from 'x402-axios'
|
import { withPaymentInterceptor } from 'x402-axios'
|
||||||
import { mnemonicToAccount } from 'viem/accounts'
|
import { privateKeyToAccount } from 'viem/accounts'
|
||||||
import { baseSepolia } from 'viem/chains'
|
import { base } from 'viem/chains'
|
||||||
|
// import { baseSepolia } from 'viem/chains' // Testnet
|
||||||
|
|
||||||
import { createWalletClient, http } from 'viem'
|
import { createWalletClient, http } from 'viem'
|
||||||
|
|
||||||
const baseURL = 'http://localhost:5942'
|
const baseURL = 'http://localhost:5942'
|
||||||
const endpointPath = '/v6/full-node/blockchain/getBlockchainInfo'
|
const endpointPath = '/v6/full-node/blockchain/getBlockchainInfo'
|
||||||
const mnemonic = process.env.MNEMONIC || ''
|
const pKey = process.env.PRIVATE_KEY || ''
|
||||||
|
|
||||||
if (!mnemonic) throw new Error('MNEMONIC env required!')
|
|
||||||
|
|
||||||
|
// PRIVATE_KEY=0x... node examples/08-x402-axios-client.js
|
||||||
|
if (!pKey) throw new Error('PRIVATE_KEY env required!')
|
||||||
|
console.log('pKey', pKey)
|
||||||
// Create a wallet client
|
// Create a wallet client
|
||||||
const account = mnemonicToAccount(mnemonic)
|
const account = privateKeyToAccount(pKey)
|
||||||
const client = createWalletClient({
|
const client = createWalletClient({
|
||||||
account,
|
account,
|
||||||
transport: http(),
|
transport: http(),
|
||||||
chain: baseSepolia
|
chain: base
|
||||||
})
|
})
|
||||||
|
|
||||||
const api = withPaymentInterceptor(
|
const api = withPaymentInterceptor(
|
||||||
axios.create({
|
axios.create({
|
||||||
baseURL
|
baseURL,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
client
|
client
|
||||||
)
|
)
|
||||||
Generated
+265
-4
@@ -9,7 +9,10 @@
|
|||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@coinbase/cdp-sdk": "1.45.0",
|
||||||
"@psf/bch-js": "7.1.11",
|
"@psf/bch-js": "7.1.11",
|
||||||
|
"@x402/core": "2.6.0",
|
||||||
|
"@x402/evm": "2.6.0",
|
||||||
"axios": "1.7.7",
|
"axios": "1.7.7",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"dotenv": "16.3.1",
|
"dotenv": "16.3.1",
|
||||||
@@ -19,8 +22,9 @@
|
|||||||
"slp-token-media": "1.2.10",
|
"slp-token-media": "1.2.10",
|
||||||
"winston": "3.11.0",
|
"winston": "3.11.0",
|
||||||
"winston-daily-rotate-file": "4.7.1",
|
"winston-daily-rotate-file": "4.7.1",
|
||||||
"x402-axios": "^1.1.0",
|
"x402-axios": "1.1.0",
|
||||||
"x402-express": "1.1.0"
|
"x402-express": "1.1.0",
|
||||||
|
"x402-fetch": "1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"apidoc": "1.2.0",
|
"apidoc": "1.2.0",
|
||||||
@@ -4182,6 +4186,49 @@
|
|||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@spruceid/siwe-parser": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@spruceid/siwe-parser/-/siwe-parser-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-d/r3S1LwJyMaRAKQ0awmo9whfXeE88Qt00vRj91q5uv5ATtWIQEGJ67Yr5eSZw5zp1/fZCXZYuEckt8lSkereQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "^1.1.2",
|
||||||
|
"apg-js": "^4.3.0",
|
||||||
|
"uri-js": "^4.4.1",
|
||||||
|
"valid-url": "^1.0.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@stablelib/binary": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stablelib/binary/-/binary-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@stablelib/int": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@stablelib/int": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stablelib/int/-/int-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@stablelib/random": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stablelib/random/-/random-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@stablelib/binary": "^1.0.1",
|
||||||
|
"@stablelib/wipe": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@stablelib/wipe": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@swc/helpers": {
|
"node_modules/@swc/helpers": {
|
||||||
"version": "0.5.19",
|
"version": "0.5.19",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.19.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.19.tgz",
|
||||||
@@ -5253,6 +5300,64 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@x402/core": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@x402/core/-/core-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-ISC/JeVss6xlKvor2rp18tJf9K5OQlIDDfZW1VZJQGDI2F4gy+HWxxkFfcQalCsPp4YUlwqh0YOkUxP+LTZWVg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"zod": "^3.24.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@x402/evm": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@x402/evm/-/evm-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-wPkNHf483gie1Up2sJSvERnW+VIEvMoT1KRXr09wSoSWgelglsJm+ug3gPPXKnT3C6AcmNAKZ12rBnu9Paff7g==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@x402/core": "~2.6.0",
|
||||||
|
"@x402/extensions": "~2.6.0",
|
||||||
|
"viem": "^2.39.3",
|
||||||
|
"zod": "^3.24.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@x402/extensions": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@x402/extensions/-/extensions-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-aLY9xAOOiRLKDN9HT2r9TYUXbD+IsoBces9qPZNVJGO2TBi2rfmbIBc3pcKCtWKn3iTvG2QFr3gpOFdpJRzqww==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@scure/base": "^1.2.6",
|
||||||
|
"@x402/core": "~2.6.0",
|
||||||
|
"ajv": "^8.17.1",
|
||||||
|
"siwe": "^2.3.2",
|
||||||
|
"tweetnacl": "^1.0.3",
|
||||||
|
"viem": "^2.43.5",
|
||||||
|
"zod": "^3.24.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@x402/extensions/node_modules/ajv": {
|
||||||
|
"version": "8.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
|
||||||
|
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.3",
|
||||||
|
"fast-uri": "^3.0.1",
|
||||||
|
"json-schema-traverse": "^1.0.0",
|
||||||
|
"require-from-string": "^2.0.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@x402/extensions/node_modules/json-schema-traverse": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@xtuc/ieee754": {
|
"node_modules/@xtuc/ieee754": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||||
@@ -5333,6 +5438,13 @@
|
|||||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/aes-js": {
|
||||||
|
"version": "4.0.0-beta.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz",
|
||||||
|
"integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/agentkeepalive": {
|
"node_modules/agentkeepalive": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
|
||||||
@@ -5438,6 +5550,12 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/apg-js": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/apg-js/-/apg-js-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-fefmXFknJmtgtNEXfPwZKYkMFX4Fyeyz+fNF6JWp87biGOPslJbCBVU158zvKRZfHBKnJDy8CMM40oLFGkXT8Q==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
"node_modules/apidoc": {
|
"node_modules/apidoc": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-1.2.0.tgz",
|
||||||
@@ -9010,6 +9128,114 @@
|
|||||||
"url": "https://paulmillr.com/funding/"
|
"url": "https://paulmillr.com/funding/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ethers": {
|
||||||
|
"version": "6.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz",
|
||||||
|
"integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/ethers-io/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://www.buymeacoffee.com/ricmoo"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@adraffy/ens-normalize": "1.10.1",
|
||||||
|
"@noble/curves": "1.2.0",
|
||||||
|
"@noble/hashes": "1.3.2",
|
||||||
|
"@types/node": "22.7.5",
|
||||||
|
"aes-js": "4.0.0-beta.5",
|
||||||
|
"tslib": "2.7.0",
|
||||||
|
"ws": "8.17.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ethers/node_modules/@adraffy/ens-normalize": {
|
||||||
|
"version": "1.10.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz",
|
||||||
|
"integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/ethers/node_modules/@noble/curves": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "1.3.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ethers/node_modules/@noble/hashes": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ethers/node_modules/@types/node": {
|
||||||
|
"version": "22.7.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
|
||||||
|
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~6.19.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ethers/node_modules/tslib": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
|
||||||
|
"license": "0BSD",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/ethers/node_modules/undici-types": {
|
||||||
|
"version": "6.19.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||||
|
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/ethers/node_modules/ws": {
|
||||||
|
"version": "8.17.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||||
|
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eventemitter2": {
|
"node_modules/eventemitter2": {
|
||||||
"version": "6.4.9",
|
"version": "6.4.9",
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz",
|
||||||
@@ -13046,7 +13272,6 @@
|
|||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
@@ -14173,6 +14398,21 @@
|
|||||||
"url": "https://opencollective.com/sinon"
|
"url": "https://opencollective.com/sinon"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/siwe": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/siwe/-/siwe-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-aSf+6+Latyttbj5nMu6GF3doMfv2UYj83hhwZgUF20ky6fTS83uVhkQABdIVnEuS8y1bBdk7p6ltb9SmlhTTlA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@spruceid/siwe-parser": "^2.1.2",
|
||||||
|
"@stablelib/random": "^1.0.1",
|
||||||
|
"uri-js": "^4.4.1",
|
||||||
|
"valid-url": "^1.0.9"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"ethers": "^5.6.8 || ^6.0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/slp-mdm": {
|
"node_modules/slp-mdm": {
|
||||||
"version": "0.0.7",
|
"version": "0.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/slp-mdm/-/slp-mdm-0.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/slp-mdm/-/slp-mdm-0.0.7.tgz",
|
||||||
@@ -14978,6 +15218,12 @@
|
|||||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
|
"node_modules/tweetnacl": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==",
|
||||||
|
"license": "Unlicense"
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
@@ -15377,7 +15623,6 @@
|
|||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
@@ -15467,6 +15712,11 @@
|
|||||||
"node": ">=10.12.0"
|
"node": ">=10.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/valid-url": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA=="
|
||||||
|
},
|
||||||
"node_modules/valtio": {
|
"node_modules/valtio": {
|
||||||
"version": "1.13.2",
|
"version": "1.13.2",
|
||||||
"resolved": "https://registry.npmjs.org/valtio/-/valtio-1.13.2.tgz",
|
"resolved": "https://registry.npmjs.org/valtio/-/valtio-1.13.2.tgz",
|
||||||
@@ -16939,6 +17189,17 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/x402-fetch": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/x402-fetch/-/x402-fetch-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-cbuUrb258+5n/oZxnvw454+iuhBoFkLptr4WEvlcCi8Hg1utIA6n0O1KqXdBV7GgNmQ8LoUDOiVv9DEyIvnlTw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"viem": "^2.21.26",
|
||||||
|
"x402": "^1.1.0",
|
||||||
|
"zod": "^3.24.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xdg-basedir": {
|
"node_modules/xdg-basedir": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
|
||||||
|
|||||||
+5
-1
@@ -15,7 +15,10 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "REST API proxy to Bitcoin Cash infrastructure",
|
"description": "REST API proxy to Bitcoin Cash infrastructure",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@coinbase/cdp-sdk": "1.45.0",
|
||||||
"@psf/bch-js": "7.1.11",
|
"@psf/bch-js": "7.1.11",
|
||||||
|
"@x402/core": "2.6.0",
|
||||||
|
"@x402/evm": "2.6.0",
|
||||||
"axios": "1.7.7",
|
"axios": "1.7.7",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"dotenv": "16.3.1",
|
"dotenv": "16.3.1",
|
||||||
@@ -26,7 +29,8 @@
|
|||||||
"winston": "3.11.0",
|
"winston": "3.11.0",
|
||||||
"winston-daily-rotate-file": "4.7.1",
|
"winston-daily-rotate-file": "4.7.1",
|
||||||
"x402-axios": "1.1.0",
|
"x402-axios": "1.1.0",
|
||||||
"x402-express": "1.1.0"
|
"x402-express": "1.1.0",
|
||||||
|
"x402-fetch": "1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"apidoc": "1.2.0",
|
"apidoc": "1.2.0",
|
||||||
|
|||||||
Vendored
+2
-1
@@ -33,10 +33,11 @@ const priceUSDC = Number.isFinite(parsedPrice) && parsedPrice > 0 ? parsedPrice
|
|||||||
|
|
||||||
const x402Defaults = {
|
const x402Defaults = {
|
||||||
enabled: normalizeBoolean(process.env.X402_ENABLED, true),
|
enabled: normalizeBoolean(process.env.X402_ENABLED, true),
|
||||||
facilitatorUrl: process.env.FACILITATOR_URL || 'http://localhost:4345/facilitator',
|
facilitatorUrl: process.env.x402_FACILITATOR_URL || 'http://localhost:4022',
|
||||||
serverAddress: process.env.SERVER_BASE_ADDRESS || 'bitcoincash:qqsrke9lh257tqen99dkyy2emh4uty0vky9y0z0lsr',
|
serverAddress: process.env.SERVER_BASE_ADDRESS || 'bitcoincash:qqsrke9lh257tqen99dkyy2emh4uty0vky9y0z0lsr',
|
||||||
facilitatorKeyId: process.env.FACILITATOR_KEY_ID || '',
|
facilitatorKeyId: process.env.FACILITATOR_KEY_ID || '',
|
||||||
facilitatorSecretKey: process.env.FACILITATOR_SECRET_KEY || '',
|
facilitatorSecretKey: process.env.FACILITATOR_SECRET_KEY || '',
|
||||||
|
network: process.env.x402_NETWORK || 'base-sepolia',
|
||||||
priceUSDC
|
priceUSDC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+49
-4
@@ -1,8 +1,10 @@
|
|||||||
import config from './index.js'
|
import config from './index.js'
|
||||||
|
import { generateJwt } from '@coinbase/cdp-sdk/auth'
|
||||||
|
|
||||||
const DEFAULT_DESCRIPTION = 'Access to protected psf-bch-api resources'
|
const DEFAULT_DESCRIPTION = 'Access to protected psf-bch-api resources'
|
||||||
const DEFAULT_TIMEOUT_SECONDS = 60
|
const DEFAULT_TIMEOUT_SECONDS = 120
|
||||||
const NETWORK = 'base-sepolia'
|
const NETWORK = config.x402.network
|
||||||
|
if (!NETWORK) throw new Error('x402_NETWORK env required!')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a route configuration map for x402-bch middleware.
|
* Builds a route configuration map for x402-bch middleware.
|
||||||
@@ -27,7 +29,15 @@ export function buildX402Routes (apiPrefix = '/v6') {
|
|||||||
network: NETWORK,
|
network: NETWORK,
|
||||||
config: {
|
config: {
|
||||||
description: `${DEFAULT_DESCRIPTION} (${config.x402.priceUSDC} USDC)`,
|
description: `${DEFAULT_DESCRIPTION} (${config.x402.priceUSDC} USDC)`,
|
||||||
maxTimeoutSeconds: DEFAULT_TIMEOUT_SECONDS
|
maxTimeoutSeconds: DEFAULT_TIMEOUT_SECONDS,
|
||||||
|
mimeType: 'application/json',
|
||||||
|
outputSchema: {
|
||||||
|
input: {
|
||||||
|
type: 'http',
|
||||||
|
method: 'GET',
|
||||||
|
discoverable: true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,7 +46,7 @@ export function buildX402Routes (apiPrefix = '/v6') {
|
|||||||
export function getX402Settings () {
|
export function getX402Settings () {
|
||||||
return {
|
return {
|
||||||
enabled: Boolean(config.x402?.enabled),
|
enabled: Boolean(config.x402?.enabled),
|
||||||
facilitatorUrl: config.x402?.facilitatorUrl, // https://docs.cdp.coinbase.com/x402/quickstart-for-sellers
|
facilitatorUrl: config.x402?.facilitatorUrl, // https://docs.cdp.coinbase.com/x402/quickstart-for-sellers
|
||||||
facilitatorKeyId: config.x402?.facilitatorKeyId,
|
facilitatorKeyId: config.x402?.facilitatorKeyId,
|
||||||
facilitatorSecretKey: config.x402?.facilitatorSecretKey,
|
facilitatorSecretKey: config.x402?.facilitatorSecretKey,
|
||||||
serverAddress: config.x402?.serverAddress,
|
serverAddress: config.x402?.serverAddress,
|
||||||
@@ -50,3 +60,38 @@ export function getBasicAuthSettings () {
|
|||||||
token: config.basicAuth?.token || ''
|
token: config.basicAuth?.token || ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Auth headers for interact with mainnet coin base facilitator endpoints.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
// https://docs.cdp.coinbase.com/get-started/authentication/jwt-authentication#javascript-2
|
||||||
|
// https://docs.cdp.coinbase.com/api-reference/v2/rest-api/x402-facilitator/verify-a-payment
|
||||||
|
export async function createAuthHeader () {
|
||||||
|
// /verify endpoint jwt
|
||||||
|
const verifyToken = await generateJwt({
|
||||||
|
apiKeyId: config.x402?.facilitatorKeyId,
|
||||||
|
apiKeySecret: config.x402?.facilitatorSecretKey,
|
||||||
|
requestMethod: 'POST',
|
||||||
|
requestHost: 'api.cdp.coinbase.com',
|
||||||
|
requestPath: '/platform/v2/x402/verify'
|
||||||
|
})
|
||||||
|
// /settle endpoint jwt
|
||||||
|
const settleToken = await generateJwt({
|
||||||
|
apiKeyId: config.x402?.facilitatorKeyId,
|
||||||
|
apiKeySecret: config.x402?.facilitatorSecretKey,
|
||||||
|
requestMethod: 'POST',
|
||||||
|
requestHost: 'api.cdp.coinbase.com',
|
||||||
|
requestPath: '/platform/v2/x402/settle'
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
verify: {
|
||||||
|
Authorization: `Bearer ${verifyToken}`
|
||||||
|
},
|
||||||
|
settle: {
|
||||||
|
Authorization: `Bearer ${settleToken}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user