Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
48e71ca
feat(backend): update sender data in incoming partial payment webhook…
njlie Feb 4, 2026
28125e9
feat(backend): add confirmPartialIncomingPayment resolver (#3819)
njlie Feb 6, 2026
921a317
feat(backend): reject partial payment gql api (#3823)
njlie Feb 13, 2026
fa44fe8
feat(backend): add middleware that handles STREAM KYC/additional data…
sanducb Apr 6, 2026
b1b8f92
fix: cherrypick 4917c14f
sanducb Apr 7, 2026
b2b70d2
chore: format
sanducb Apr 7, 2026
0a9755b
fix: remove duplicate property
sanducb Apr 7, 2026
683096a
fix: backend tests
sanducb Apr 7, 2026
aa40a06
chore: merge branch 'main' of https://github.com/interledger/rafiki i…
sanducb Apr 14, 2026
c96473d
chore: update lock file
sanducb Apr 14, 2026
d5bac6e
chore: format
sanducb Apr 14, 2026
bdc1dfa
chore: update lock file
sanducb Apr 14, 2026
918f65e
fix: attempt to fix CI builds
sanducb Apr 15, 2026
0c110a8
fix: address PR comments
sanducb Apr 16, 2026
b7adfed
feat: add encrypted data exchange docker compose variant and manual t…
BlairCurrey Apr 17, 2026
feb7411
feat: add partial payment rejection description on outgoing_payment.f…
sanducb Apr 17, 2026
1fb8054
chore: merge branch 'feature/encrypted-data-exchange' of https://gith…
sanducb Apr 17, 2026
b2a507c
fix: pin testcontainers to 10.16.0 for Tigerbeetle tests
sanducb Apr 20, 2026
8ba1392
fix: attempt to fix CI backend build
sanducb Apr 21, 2026
adfe271
chore: merge branch 'main' of https://github.com/interledger/rafiki i…
sanducb Apr 23, 2026
463c032
fix: revert testcontainers version changes and update lockfile
sanducb Apr 23, 2026
a5b236b
chore: format
sanducb Apr 23, 2026
786ca0c
fix: missing error message in outgoing payment tests
sanducb Apr 23, 2026
26b01aa
chore: minor updates for encrypted data exchange feature (#3911)
mkurapov May 4, 2026
1bc8c74
fix: use dataFromSender instead dataToTransmit when decrypting webhoo…
sanducb May 4, 2026
834e7e5
chore: update localenv doc
sanducb May 6, 2026
228ce99
chore: update RejectPartialIncomingPaymentInput reason description
sanducb May 6, 2026
b040ac8
chore: regenerate graphql types
sanducb May 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions localenv/cloud-nine-wallet/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ services:
OPERATOR_TENANT_ID: 438fa74a-fa7d-4317-9ced-dde32ece1787
CARD_SERVICE_URL: 'http://cloud-nine-wallet-card-service:3007'
CARD_WEBHOOK_SERVICE_URL: 'http://cloud-nine-wallet-card-service:3007/webhook'
DB_ENCRYPTION_SECRET: 'zO9KogehJECHReHgQr+ZWGkmgOD4AYa4ksUxALSwgM8='
depends_on:
shared-database:
condition: service_healthy
Expand Down
24 changes: 24 additions & 0 deletions localenv/docs/encrypted-data-exchange.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Run with Encrypted Data Exchange

Start the env with the feature flag enabled on the receiver:

```bash
pnpm localenv:compose:partial-payment up
```

# Manually Test the Encrypted Data Exchange Flow (Happy Path)

## Steps

- Run the **Examples > Admin API > Open Payments** or the **Examples > Open Payments > Peer-to-Peer Payment** requests in Bruno.

## Verification

In the `happy-life-bank-mock-ase` logs:

- `incoming_payment.partial_payment_received` webhook was received, with `partialIncomingPaymentId` and the `dataToTransmit` defined in the payload
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small thing but shouldn't dataToTransmit here be dataFromSender? I know there was a partial replacement of these terms but I think this one should be from sender. judging by the incomingPaymentEvent in the webhook.yaml open api spec, mock ase handleIncomingPartialPaymentReceived webhook handler, etc.

- `confirmPartialIncomingPayment` was called

In Bruno:

- Confirm the Outgoing Payment is completed by calling the `Get Outgoing Payment` request, and verifying a positive `sentAmount`.
2 changes: 2 additions & 0 deletions localenv/happy-life-bank/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ services:
SIGNATURE_VERSION: 1
SIGNATURE_SECRET: iyIgCprjb9uL8wFckR+pLEkJWMB7FJhgkvqhTQR/964=
IDP_SECRET: 2pEcn2kkCclbOHQiGNEwhJ0rucATZhrA807HTm2rNXE=
DB_ENCRYPTION_SECRET: 'zO9KogehJECHReHgQr+ZWGkmgOD4AYa4ksUxALSwgM8='
DISPLAY_NAME: Happy Life Bank
DISPLAY_ICON: bank-icon.svg
OPERATOR_TENANT_ID: cf5fd7d3-1eb1-4041-8e43-ba45747e9e5d
Expand Down Expand Up @@ -114,6 +115,7 @@ services:
OPERATOR_TENANT_ID: cf5fd7d3-1eb1-4041-8e43-ba45747e9e5d
CARD_SERVICE_URL: 'http://happy-life-bank-card-service:4007'
POS_WEBHOOK_SERVICE_URL: 'http://happy-life-bank-point-of-sale:4008/webhook'
DB_ENCRYPTION_SECRET: 'zO9KogehJECHReHgQr+ZWGkmgOD4AYa4ksUxALSwgM8='
WALLET_ADDRESS_NOT_FOUND_POLLING_ENABLED: true
depends_on:
- cloud-nine-backend
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ export async function handleOutgoingPaymentCreated(
variables: {
input: {
outgoingPaymentId: payment.id,
idempotencyKey: uuid()
idempotencyKey: uuid(),
dataToTransmit: 'sample kyc data'
}
}
})
Expand Down Expand Up @@ -186,6 +187,62 @@ export async function handleIncomingPaymentCompletedExpired(
return
}

export async function handleIncomingPartialPaymentReceived(
wh: Webhook,
options?: TenantOptions
) {
if (wh.type !== WebhookEventType.IncomingPaymentPartialPaymentReceived) {
throw new Error(
'Invalid event type when handling incoming partial payment webhook'
)
}

const incomingPaymentId = wh.data['id'] as string | undefined
if (!incomingPaymentId) {
throw new Error('No incomingPaymentId found on webhook data')
}

const partialIncomingPaymentId = wh.data['partialIncomingPaymentId'] as
| string
| undefined
if (!partialIncomingPaymentId) {
throw new Error('No partialIncomingPaymentId found on webhook data')
}

const dataFromSender = wh.data['dataFromSender'] as string | undefined
if (!dataFromSender) {
throw new Error('No dataFromSender found on webhook data')
}

await generateApolloClient(options)
.mutate({
mutation: gql`
mutation ConfirmPartialIncomingPayment(
$input: ConfirmPartialIncomingPaymentInput!
) {
confirmPartialIncomingPayment(input: $input) {
success
}
}
`,
variables: {
input: {
incomingPaymentId,
partialIncomingPaymentId
}
}
})
.then((query): LiquidityMutationResponse => {
if (query.data) {
return query.data.confirmPartialIncomingPayment
} else {
throw new Error('Data was empty')
}
})

return
}

export async function handleWalletAddressWebMonetization(
wh: Webhook,
options?: TenantOptions
Expand Down
10 changes: 6 additions & 4 deletions localenv/mock-account-servicing-entity/app/routes/webhooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import { json } from '@remix-run/node'
import {
handleLowLiquidity,
handleWalletAddressNotFound,
handleWalletAddressWebMonetization
} from '~/lib/webhooks.server'
import {
handleWalletAddressWebMonetization,
handleOutgoingPaymentCreated,
handleOutgoingPaymentCompletedFailed,
handleIncomingPaymentCompletedExpired
handleIncomingPaymentCompletedExpired,
handleIncomingPartialPaymentReceived
} from '~/lib/webhooks.server'
import { WebhookEventType, Webhook } from 'mock-account-service-lib'
import { getTenantCredentials } from '~/lib/utils'
Expand Down Expand Up @@ -36,6 +35,9 @@ export async function action({ request }: ActionFunctionArgs) {
break
case WebhookEventType.IncomingPaymentCreated:
break
case WebhookEventType.IncomingPaymentPartialPaymentReceived:
await handleIncomingPartialPaymentReceived(wh, tenantOptions)
break
case WebhookEventType.IncomingPaymentCompleted:
case WebhookEventType.IncomingPaymentExpired:
await handleIncomingPaymentCompletedExpired(wh, tenantOptions)
Expand Down
60 changes: 60 additions & 0 deletions localenv/mock-account-servicing-entity/generated/graphql.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions localenv/partial-payment/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
happy-life-backend:
environment:
ENABLE_PARTIAL_PAYMENT_DECISION: 'true'
PARTIAL_PAYMENT_DECISION_MAX_WAIT_MS: '30000'
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"build": "tsc --build",
"localenv:compose:psql": "docker compose -f ./localenv/cloud-nine-wallet/docker-compose.yml -f ./localenv/global-bank/docker-compose.yml -f ./localenv/happy-life-bank/docker-compose.yml -f ./localenv/merged/docker-compose.yml",
"localenv:compose": "docker compose -f ./localenv/cloud-nine-wallet/docker-compose.yml -f ./localenv/happy-life-bank/docker-compose.yml -f ./localenv/merged/docker-compose.yml -f ./localenv/tigerbeetle/docker-compose.yml --env-file ./localenv/tigerbeetle/.env.tigerbeetle",
"localenv:compose:partial-payment": "docker compose -f ./localenv/cloud-nine-wallet/docker-compose.yml -f ./localenv/happy-life-bank/docker-compose.yml -f ./localenv/merged/docker-compose.yml -f ./localenv/tigerbeetle/docker-compose.yml -f ./localenv/partial-payment/docker-compose.yml --env-file ./localenv/tigerbeetle/.env.tigerbeetle",
"localenv:compose:multihop": "docker compose -f ./localenv/cloud-nine-wallet/docker-compose.yml -f ./localenv/global-bank/docker-compose.yml -f ./localenv/happy-life-bank/docker-compose.yml -f ./localenv/multihop/docker-compose.yml -f ./localenv/merged/docker-compose.yml -f ./localenv/tigerbeetle/docker-compose.yml --env-file ./localenv/tigerbeetle/.env.tigerbeetle",
"localenv:compose:multitenancy": "docker compose -f ./localenv/cloud-ten-wallet/docker-compose.yml -f ./localenv/cloud-nine-wallet/docker-compose.yml -f ./localenv/happy-life-bank/docker-compose.yml -f ./localenv/merged/docker-compose.yml -f ./localenv/tigerbeetle/docker-compose.yml --env-file ./localenv/tigerbeetle/.env.tigerbeetle",
"localenv:compose:psql:telemetry": "docker compose -f ./localenv/cloud-nine-wallet/docker-compose.yml -f ./localenv/global-bank/docker-compose.yml -f ./localenv/happy-life-bank/docker-compose.yml -f ./localenv/merged/docker-compose.yml -f ./localenv/telemetry/docker-compose.yml",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = async function (knex) {
const hasColumn = await knex.schema.hasColumn(
'outgoingPayments',
'dataToTransmit'
)
if (!hasColumn) {
await knex.schema.alterTable('outgoingPayments', function (table) {
table.string('dataToTransmit').nullable()
})
}
}

/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = async function (knex) {
const hasColumn = await knex.schema.hasColumn(
'outgoingPayments',
'dataToTransmit'
)
if (hasColumn) {
await knex.schema.alterTable('outgoingPayments', function (table) {
table.dropColumn('dataToTransmit')
})
}
}
Loading
Loading