Example aopdProofs Subscription

This subscription listens to Address Ownership Proof Protocol (AOPP) proofs and will receive a notification with the full signature proof.

The aopdProofs subscription is served from /graphql-ws. Please use GraphiQL to obtain the query and returned object details.

Sample Code

Below we provide fully functional sample code that implements authentication and listens to new verified proofs via the GraphQL subscription API.

Make sure to install Node.js on your system before proceeding.

Execute the following snippet to subscribe for obtaining new verified proofs in real-time that are submitted through https://virtualcounter.testing.21analytics.xyz/withdraw/wallet. Note, that the script will print nothing if there are no proofs submitted.

mkdir proof-listener
cd proof-listener
curl -sO https://docs.21analytics.ch/7.4.0/api/subscriptions/proofs.js
npm add graphqurl@2.0.0
node proofs.js

The source code file can be downloaded here or copy and pasted from the snippet below. Change the values of the constant variables indicated by comments starting with ❗to make the sample code work against your own 21 Travel Rule deployment.

// Copyright (c) 2024 21 Analytics AG. All Rights Reserved.

const { createClient } = require("graphqurl")

// ❗
// change the GRAPHQL_SUBSCRIPTION_URL value to the
// one you have configured following this guide (usually,
// only the host needs to be adjusted):
// https://docs.21analytics.ch/7.4.0/deployment/deployment.html
const GRAPHQL_SUBSCRIPTION_URL = new URL(
    "wss://testing.21analytics.xyz/graphql-ws",
)

// ❗
// change the CLIENT_SECRET and CLIENT_ID values to the ones
// you have configured following this guide:
// https://docs.21analytics.ch/7.4.0/api/authentication.html
const CLIENT_SECRET = "gAlyXb1IR3BrNZw3gaB4Q5Ve3cVwP7g6"
const CLIENT_ID = "21travel-aopdProofs-demo"

const subscription = `subscription AopdProofs {
                        aopdProofs {
                          __typename
                          ... on AopdSignatureProof {
                            id
                            address
                            asset
                            riskScores
                          }
                          ... on AopdMediaProof {
                            id
                            address
                            asset
                            riskScores
                          }
                          ... on AopdSatoshiProof {
                            id
                            address: senderAddress
                            asset
                            riskScores
                          }
                        }
                      }`

const body = new URLSearchParams()
body.append("grant_type", "client_credentials")
body.append("scope", "openid")
body.append("client_id", CLIENT_ID)
body.append("client_secret", CLIENT_SECRET)

fetch(
    `https://${GRAPHQL_SUBSCRIPTION_URL.host}/auth/realms/21travel/protocol/openid-connect/token`,
    { method: "POST", body },
)
    .then((data) => data.json())
    .then((json) => json.access_token)
    .then((bearer_token) => {
        const client = createClient({
            websocket: {
                endpoint: GRAPHQL_SUBSCRIPTION_URL,
                onConnectionError: console.error,
                onConnectionSuccess: () => {
                    client.subscribe(
                        { subscription },
                        ({ data }) => {
                            console.log(
                                `✅ received new valid proof with id: ${data.aopdProofs.id}`,
                            )
                        },
                        console.error,
                    )
                },
                parameters: { bearer_token },
            },
        })
    })