You have sent your first Payload request and also signed and/or rejected the sign request, by scanning the QR code. Now lets see how we can get user specific user token and start sending sign request as push notification to the end user.
Payload using create() method
const {XummSdk} = require('xumm-sdk') const Sdk = new XummSdk('xumm-app-id', 'xumm-app-secret') const main = async () => { const request = { "TransactionType": "Payment", "Destination": "rHdkzpxr3VfabJh9tUEDv7N4DJEsA4UioT", "Amount": "1000000" } const payload = await Sdk.payload.create(request, true) console.log(payload) } main()
Above code is from our previous video tutorial where we sent our first payload using create method.
Video Tutorial: Send Sign Request As Push Notification: XUMM SDK
[youtube https://www.youtube.com/watch?v=4Wxcz0jvA9A]
Payload using createAndSubscribe() method
const {XummSdk} = require('xumm-sdk') const Sdk = new XummSdk('xumm-app-id', 'xumm-app-secret') const main = async () => { const request = { "TransactionType": "Payment", "Destination": "rHdkzpxr3VfabJh9tUEDv7N4DJEsA4UioT", "Amount": "1000000" } const subscription = await Sdk.payload.createAndSubscribe(request, event => { console.log('New payload event',event.data) }) console.log('sign request URL',subscription.created.next.always) console.log('Pushed ',subscription.created.pushed) } main()
Here we use createAndSubscribe() method instead of create() method. createAndSubscribe() also takes 2 arguments. The first argument is the payload information and the second argument is method/function that gets invoked every time the XUMM platform asynchronously sends an update about the created payload.
Running The Application
We issue the command node index.js to run our application and we get the following output:
sign request URL https://xumm.app/sign/e917182a-b64f-474d-ab24-8792d6b0ca6c Pushed false New payload event { message: 'Welcome e917182a-b64f-474d-ab24-8792d6b0ca6c' } New payload event { expires_in_seconds: 86399 } New payload event { expires_in_seconds: 86384 }
Since main() is a asynchronous method and a child thread keeps waiting for Sdk.payload.createAndSubscribe() method to be resolved(it gets resolved once end user either signs or rejects the sign request, or when the payload expires). If we want to exit the waiting and kill the child process – get on the output terminal and press CTRL + C buttons(on windows PC).
The constant subscription(from above code) has information regarding the payload, payload status, signing URL, QR code information etc. Sdk.payload.createAndSubscribe() second argument keeps updating the payload status like expiration time until the user performs some action on the sign request. If user doesn’t perform any action until the payload gets expired, then the payload information gets expired and will be removed from the XUMM platform.
Once Payload is Resolved
Once user opens the QR code present on sign request URL(check above code output), scans it and signs or rejects the sign request, the method in seconds argument of Sdk.payload.createAndSubscribe() gets triggered and sends the updated status of the sign request.
const {XummSdk} = require('xumm-sdk') const Sdk = new XummSdk('xumm-app-id', 'xumm-app-secret') const main = async () => { const request = { "TransactionType": "Payment", "Destination": "rHdkzpxr3VfabJh9tUEDv7N4DJEsA4UioT", "Amount": "1000000" } const subscription = await Sdk.payload.createAndSubscribe(request, event => { console.log('New payload event',event.data) if(Object.keys(event.data).indexOf('signed') > -1) { return event.data } }) console.log('sign request URL',subscription.created.next.always) console.log('Pushed ',subscription.created.pushed) } main()
The Object.keys you see in above code is standard Javascript code. When we pass an object to it, and chain indexOf() method and pass the key name to indexOf() method, it returns the index position of that key in the object. Index starts from 0. So it returns the event.data if and when the user interacts with the payload QR code and either signs or rejects the payload. Until user performs some action with the generated payload, event.data will not have the key signed in its output.
Lets execute above code
We issue the command node index.js to run our application and we get the following output:
sign request URL https://xumm.app/sign/e917182a-b64f-474d-ab24-8792d6b0ca6c Pushed false New payload event { message: 'Welcome e917182a-b64f-474d-ab24-8792d6b0ca6c' } New payload event { expires_in_seconds: 86399 } New payload event { expires_in_seconds: 86384 }
Copy the sign request URL from above output and past it in a browser and open your XUMM app in your phone, scan the QR code and sign or reject the sign request and look out for the status change.
Output when the sign request gets rejected
sign request URL https://xumm.app/sign/972d25fe-413a-48a3-8935-dd95c6cdf8ef Pushed false New payload event { message: 'Welcome 972d25fe-413a-48a3-8935-dd95c6cdf8ef' } New payload event { expires_in_seconds: 86399 } New payload event { expires_in_seconds: 86384 } New payload event { opened: true } New payload event { payload_uuidv4: '972d25fe-413a-48a3-8935-dd95c6cdf8ef', reference_call_uuidv4: 'd81ae124-527d-40b6-ad38-c272f9b71134', signed: false, user_token: true, return_url: { app: null, web: null }, opened_by_deeplink: false, custom_meta: { identifier: null, blob: null, instruction: null } }
As you can see in the output above, the payload event status shows when the user opened his/her XUMM app and scanned the QR code { opened: true }. In above case the end user has rejected the sign request, so the signed key has a value of false. The key opened_by_deeplink is new and is implemented in XUMM SDK 0.2.2 to further improve user flows – its value is null if unopened, true if opened using a mobile deeplink/push, false if QR scan opened. Technically it is present to let the developer know whether the sign request was opened from a deeplink URL or not.
Output when the sign request is signed
sign request URL https://xumm.app/sign/848ff099-4161-4911-a024-d27c15e87f62 Pushed false New payload event { message: 'Welcome 848ff099-4161-4911-a024-d27c15e87f62' } New payload event { expires_in_seconds: 86399 } New payload event { opened: true } New payload event { expires_in_seconds: 86384 } New payload event { payload_uuidv4: '848ff099-4161-4911-a024-d27c15e87f62', reference_call_uuidv4: 'bc98f5b6-d960-41a3-884a-3c9dced5b0e2', signed: true, user_token: true, return_url: { app: null, web: null }, opened_by_deeplink: false, custom_meta: { identifier: null, blob: null, instruction: null } }
As you can see from above output, the value of signed is true. That means end user has successfully signed the sign request. Now we take the payload_uuidv4 value and fetch the user token from it.
Fetching user_token from payload_uuidv4
const {XummSdk} = require('xumm-sdk') const Sdk = new XummSdk('xumm-app-id', 'xumm-app-secret') const main = async () => { const request = { "TransactionType": "Payment", "Destination": "rHdkzpxr3VfabJh9tUEDv7N4DJEsA4UioT", "Amount": "1000000" } const subscription = await Sdk.payload.createAndSubscribe(request, event => { // console.log('New payload event',event.data) if(Object.keys(event.data).indexOf('signed') > -1) { return event.data } }) console.log('sign request URL',subscription.created.next.always) console.log('Pushed ',subscription.created.pushed ? 'Yes' : 'No') const resolveData = await subscription.resolved if(resolveData.signed == false) { console.log('The sign request was rejected!') } else { console.log('The sign request was Signed!!') const result = await Sdk.payload.get(resolveData.payload_uuidv4) console.log('User_token: ',result.application) } } main()
We take another constant and await for subscription to be resolved. Once the end user signs the sign request we pass the resolveData.payload_uuidv4 information to Sdk.payload.get() which outputs a lot of json results. In that we pick up the user_token present under result.application as value for key issued_user_token.
Output of above code:
sign request URL https://xumm.app/sign/da54ac54-549f-42d2-a239-8ae6086eafbd Pushed No New payload event { message: 'Welcome da54ac54-549f-42d2-a239-8ae6086eafbd' } New payload event { expires_in_seconds: 86397 } New payload event { opened: true } New payload event { expires_in_seconds: 86382 } The sign request was Signed!! User_token: { name: 'My Super Duper App!', description: 'Demo App To Show New SDK Features', disabled: 0, uuidv4: '401015ee-7edc-4469-bdfd-3af11f229885', icon_url: 'https://xumm-cdn.imgix.net/app-logo/2a14d2f7-d0a8-432a-a40f-b45eddb70fc4.png', issued_user_token: '343a2f1e-8160-4984-a0f0-208086509617' }
In this we are interested in issued_user_token, which will be used to send push notifications to end user. To pick it up we write result.application.issued_user_token and store it inside the database.
Sending sign request as Push Notification
The user_token is a unique token for your XUMM app in combination with the specific XUMM user. To use the token to deliver a sign requst per Push notification, let’s adjust our first (minimal) sample payload or the ‘transaction template’ to include the user token:
This payload is XRPL specific
const request = { "TransactionType": "Payment", "Destination": "rHdkzpxr3VfabJh9tUEDv7N4DJEsA4UioT", "Amount": "10000", }
Now lets add user_token information to it.
{ "txjson": { "TransactionType": "Payment", "Destination": "rHdkzpxr3VfabJh9tUEDv7N4DJEsA4UioT", "Amount": "10000" }, "user_token": "343a2f1e-8160-4984-a0f0-208086509617" }
As you can see from above code, all the XRP Ledger specific payload information has been moved into a separate block under key txjson. All the other information outside of object txjson is specific to XUMM platform. Other XUMM platform specific information are: options, custom_meta and the user_token etc.
Stage is set to send sign request as Push Notification
Now lets use the user_token we received from our previously signed payload and use that in our final source code. Once you execute this final source code, the end user(user identified by user_token) will receive the sign request as push notification. Exciting!!
Source Code: To Send Sign Request As Push Notification: XUMM SDK
const {XummSdk} = require('xumm-sdk') const {Txdata, TxData} = require('xrpl-txdata') const Sdk = new XummSdk('401015ee-7edc-4469-bdfd-3af11f229885', '267b909b-0374-450b-a05b-5df60bc1f57a') const Verify = new TxData() const main = async() => { const request = { "txjson": { "TransactionType": "Payment", "Destination": "rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ", "Amount": "1000000" }, "user_token": "343a2f1e-8160-4984-a0f0-208086509617" } const subscription = await Sdk.payload.createAndSubscribe(request, event => { if(Object.keys(event.data).indexOf('signed') > -1) { return event.data } }) console.log('sign request URL',subscription.created.next.always) console.log('Pushed ',subscription.created.pushed ? 'Yes' : 'No') const resolveData = await subscription.resolved if(resolveData.signed == false) { console.log('The sign request was rejected!') } else { console.log('The sign request was Signed!!') const result = await Sdk.payload.get(resolveData.payload_uuidv4) console.log('User_token: ',result.application.issued_user_token) } } main()
Here is the push notification on my phone
We can click on the push notification bubble or open the XUMM App directly on our phone and navigate to “Events” tab and open the new sign request there and choose to sign or reject the request.
Output
The output of above source code will be same as we’ve posted previously for signing and rejecting the sign request. Now the only difference is, value of key pushed will be true as sign request was sent as push notification directly to the end users phone.
Important Note
Its best practice to check the value of key pushed in the output. If its false(maybe user revoked the permission), then its always good to show the user with the QR code to manually scan and make the payment. If value of pushed is false, that means the end user has not received the push notification.
For full “XUMM SDK/API” free video tutorial list visit: Working With XUMM SDK/API: XRPL