Skip to content

Commit 43096a8

Browse files
authored
Merge pull request #956 from sandwichfarm/fix/rstate-contextvm-sdk-013
Align rstate with ContextVM SDK 0.13
2 parents 24f897e + 15bacad commit 43096a8

8 files changed

Lines changed: 266 additions & 152 deletions

File tree

apps/rstate/.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ CVM_AUTH_ALLOW_ANY=false
3333
# CEP-8 CVM Payments
3434
CVM_PAYMENTS_ENABLED=false
3535
CVM_NWC_CONNECTION_STRING=
36+
CVM_PAYMENT_INTERACTION_POLICY=optional
3637
# CVM_PRICING_YAML=./config/pricing.cvm.yaml # optional CVM-specific overrides
3738

3839
# ========================================

apps/rstate/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,10 @@
3535
"docker:stop": "docker-compose down"
3636
},
3737
"dependencies": {
38-
"@contextvm/sdk": "^0.6.2",
38+
"@contextvm/sdk": "^0.13.9",
3939
"@fastify/cors": "^11.1.0",
4040
"@fastify/swagger": "^9.5.2",
4141
"@modelcontextprotocol/sdk": "^1.26.0",
42-
"@noble/hashes": "^1.5.0",
4342
"@noble/secp256k1": "^2.1.0",
4443
"@nostrwatch/announce": "workspace:^",
4544
"@nostrwatch/publisher": "workspace:^",
@@ -60,7 +59,7 @@
6059
"@types/ws": "^8.5.13",
6160
"tsup": "^8.3.5",
6261
"tsx": "^4.19.2",
63-
"typescript": "^5.7.2",
62+
"typescript": "^5.9.3",
6463
"vitest": "^3.2.6"
6564
},
6665
"engines": {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { PaymentInteractionPolicy } from '@contextvm/sdk'
2+
3+
const DEFAULT_CVM_PAYMENT_INTERACTION_POLICY: PaymentInteractionPolicy = 'optional'
4+
5+
export function resolveCvmPaymentInteractionPolicy(
6+
env: { [key: string]: string | undefined } = process.env
7+
): PaymentInteractionPolicy {
8+
const rawPolicy = env.CVM_PAYMENT_INTERACTION_POLICY?.trim()
9+
10+
if (!rawPolicy) return DEFAULT_CVM_PAYMENT_INTERACTION_POLICY
11+
if (rawPolicy === 'optional' || rawPolicy === 'transparent') return rawPolicy
12+
13+
throw new Error(
14+
`CVM_PAYMENT_INTERACTION_POLICY must be "optional" or "transparent"; got "${rawPolicy}"`
15+
)
16+
}

apps/rstate/src/resilient-relay-pool.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ export class ResilientRelayPool implements RelayPool {
171171
this.subscriptions.clear()
172172
logger.info('RelayHandler: all subscriptions unsubscribed')
173173
},
174+
getRelayUrls: () => this.relays.map(relay => relay.url),
174175
}
175176
}
176177

apps/rstate/src/server.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
88
import { NostrServerTransport, PrivateKeySigner, EncryptionMode, withServerPayments, LnBolt11NwcPaymentProcessor } from '@contextvm/sdk'
99
import { loadPricedCapabilities } from './payments/cvm-pricing.js'
10+
import { resolveCvmPaymentInteractionPolicy } from './payments/cvm-payment-policy.js'
1011
import { ResilientRelayPool } from './resilient-relay-pool.js'
1112
import type { Config } from './config.js'
1213
import { getLogger } from './utils/logger.js'
@@ -207,7 +208,7 @@ export class CVMServer {
207208
name: 'RelayVM',
208209
about: 'ContextVM server that aggregates NIP-66 relay intelligence and exposes it via MCP over Nostr. Service provided by nostr.watch',
209210
},
210-
isPublicServer: cvmConfig.allowedPubkeys.length === 0,
211+
isAnnouncedServer: cvmConfig.allowedPubkeys.length === 0,
211212
allowedPublicKeys: cvmConfig.allowedPubkeys.length > 0 ? cvmConfig.allowedPubkeys : undefined,
212213
})
213214

@@ -224,13 +225,18 @@ export class CVMServer {
224225
})
225226

226227
const pricedCapabilities = loadPricedCapabilities()
228+
const paymentInteraction = resolveCvmPaymentInteractionPolicy()
227229

228230
this.transport = withServerPayments(this.transport, {
229231
processors: [nwcProcessor],
230232
pricedCapabilities,
233+
paymentInteraction,
231234
})
232235

233-
logger.info({ pricedTools: pricedCapabilities.length }, 'CVM payment gating enabled (CEP-8)')
236+
logger.info({
237+
pricedTools: pricedCapabilities.length,
238+
paymentInteraction,
239+
}, 'CVM payment gating enabled (CEP-8)')
234240
}
235241

236242
// DISABLED: Subscription system
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { resolveCvmPaymentInteractionPolicy } from '../src/payments/cvm-payment-policy.js'
3+
4+
describe('CVM payment interaction policy', () => {
5+
it('defaults to the ContextVM 0.13 optional lifecycle policy', () => {
6+
expect(resolveCvmPaymentInteractionPolicy({})).toBe('optional')
7+
})
8+
9+
it('accepts transparent-only compatibility mode', () => {
10+
expect(resolveCvmPaymentInteractionPolicy({ CVM_PAYMENT_INTERACTION_POLICY: 'transparent' })).toBe('transparent')
11+
})
12+
13+
it('accepts the explicit optional policy value', () => {
14+
expect(resolveCvmPaymentInteractionPolicy({ CVM_PAYMENT_INTERACTION_POLICY: ' optional ' })).toBe('optional')
15+
})
16+
17+
it('rejects wire-level payment interaction modes as server policy values', () => {
18+
expect(() => resolveCvmPaymentInteractionPolicy({
19+
CVM_PAYMENT_INTERACTION_POLICY: 'explicit_gating',
20+
})).toThrow('CVM_PAYMENT_INTERACTION_POLICY must be "optional" or "transparent"')
21+
})
22+
})

0 commit comments

Comments
 (0)