VeChain Docs
  • Welcome to VeChain
  • Blockchain Basics
    • Introduction to blockchain
    • Introduction to digital property
    • The evolution of the internet
  • Introduction to VeChain
    • About the VeChain blockchain
      • Consensus Deep Dive
      • Governance
    • Dual-Token Economic Model
      • VeChain (VET)
      • VeThor (VTHO)
    • Acquire VeChain Assets
    • Sustainability
  • Core Concepts
    • Networks
      • Thor Solo Node
      • Testnet
      • Mainnet
    • Nodes
      • Node Rewards Programme
    • Blocks
      • Block Model
    • Transactions
      • Transaction Model
      • Transaction Fees
      • Transaction Calculation
      • Meta Transaction Features
        • Transaction Uniqueness
        • Controllable Transaction Lifecycle
        • Clauses (Multi-Task Transaction)
        • Fee Delegation
          • Multi-Party Payment (MPP)
          • Designated Gas Payer (VIP-191)
        • Transaction Dependency
    • Block Explorers
    • Wallets
      • VeWorld
        • User Guide
          • Setup
          • Wallet
          • Signing
          • Activities
          • Settings
        • FAQ
      • Sync2
        • User Guide
          • Setup
          • Wallet
          • Signing
          • Activities
          • Settings
        • FAQ
      • Sync
        • User Guide
          • Wallet
          • Ledger Device
          • Browser dApps and web
          • Interact with dApps
          • Activities
          • Settings
          • Report an Issue
          • Contributing
        • FAQ
    • EVM Compatibility
      • VeChain Modifications
      • Methodology
      • Test Coverage
        • Gas model
        • Raw transaction
        • hardhat specific
          • Ganache failures
          • evm_increaseTime
        • Failures in constructor
        • eth_sign
        • Contract address prediction
        • BadBeacon proxy address at 0x1
      • How to Recreate
      • Additional Information
        • Using Governance Contracts
        • ERC1820/ERC777 Testnet
        • Delegate Options
    • Account Abstraction
      • UserOperation
      • Bundler
      • EntryPoint Contract
      • Account Factory Contract
      • Paymaster Contract
    • Token Bound Accounts
  • How to run a node
    • Nodes
    • How to run a Thor Solo Node
    • Custom Network
    • Connect Sync2 to a Thor Solo Node
  • Developer Resources
    • Getting Started
    • How to build on VeChain
      • Connect to the Network
      • Read Data
        • Read Blocks
        • Read Transactions
        • Read Accounts
        • States & Views
        • Events & Logs
        • VET Transfers
      • Write Data
        • Transactions
        • Fee Delegation
      • Listen to Changes
        • Events
        • VET Transfers
        • Transactions
        • Blocks
        • Beats
      • Build with Hardhat
      • Utilities
        • BigInt and Unit-Handling
        • Name Service Lookups
    • Example dApps
      • Buy me a Coffee
      • Token Bound Accounts
      • PWA with Privy and Account Abstraction
    • EVM Compatibility for Developers
      • Key Architectural Differences and Optimizations
      • Practical Implications for Developers: Key Considerations
      • RPC Methods (Detailed Breakdown)
      • Frequently Asked Questions (FAQs)
      • VeChain Blockchain Specifications
      • Key Differences Between VeChain and Ethereum (Summary)
      • Best Practices for Developing on VeChainThor
    • How to verify Address-Ownership
      • Next.js Session Verification
    • Debug Reverted Transactions
    • Account Abstraction
    • VIP-191: Designated Gas Payer
      • How to Integrate VIP-191 (I)
      • How to Integrate VIP-191 (II)
      • How to Integrate VIP-191 (III)
    • Index with Graph Node
      • Setup with Docker
      • Index with OpenZeppelin
        • Create Subgraph Project
        • Configure Contracts
        • Deploy Subgraph and start Indexing
        • Track Subgraph Indexing
        • Access Subgraph
        • Update Subgraph
    • SDKs & Providers
      • SDK
        • Architecture
        • Accounts
        • Bloom Filter
        • Certificates
        • Contracts
        • Cryptography
        • Debug
        • Encoding
        • Polls
        • Subscriptions
        • Thor Client
        • Transactions
      • Thor DevKit
        • Installation
        • Usage
          • Cryptography
          • Accounts
          • Encoding
          • Transactions
          • Certificates
          • Bloom Filter
      • DApp Kit
        • v2
          • Installation
          • React
            • Installation
            • Usage
          • Vanilla JS
            • Installation
            • Usage
          • Core
            • Installation
            • Usage
          • Theme Variables
          • i18n
        • v1
          • Installation
          • React
            • Installation
            • Usage
          • Vanilla JS
            • Installation
            • Usage
          • Core
            • Installation
            • Usage
          • Theme Variables
          • i18n
          • Node Polyfills
          • V0 to V1
        • v0
          • Installation
          • Usage
          • React
            • Installation
            • Usage
          • Vanilla (UI)
            • Installation
            • Usage
          • Styles (UI)
          • i18n
      • DevPal
      • Web3-Providers-Connex
        • Installation
        • Usage
      • Connex
        • Installation
        • API Specification
    • Frameworks & IDEs
      • Hardhat
      • Remix
    • Built-in Contracts
    • VORJ
    • Useful Links
  • How to contribute
Powered by GitBook
On this page

Was this helpful?

  1. Developer Resources
  2. VIP-191: Designated Gas Payer

How to Integrate VIP-191 (III)

PreviousHow to Integrate VIP-191 (II)NextIndex with Graph Node

Last updated 12 months ago

Was this helpful?

This is the last part of the tutorial.

It mainly explains the sponsor’s initiative to inspect the transaction and sign his signature on it. We will use the express.js library to build a framework to receive transmission and return the result.

Before that, I have a hefty wallet on test-net to be a sponsor:

Sponsor’s address: 0x126cdb344f476f25b9fb2050513f425a82f71046

Private key: 5df5e7f22a71dfd3d032ff5eb9dfc7dbe9c950e0671745826639a0423cd45d7f

Balance: [] ← Contains >4000 VTHO to be spent.

Sponsor’s Server Code


const express = require('express')
const cry = require('thor-devkit/dist/cry')
const Transaction = require('thor-devkit/dist/transaction').Transaction

const app = express()
app.use(express.json())
const port = 3000

app.post('/', function(req, res) {

    // Re-construct the transaction from the request.
    const tx = new Transaction(req.body['txBody'])
    // Extract 'sender' address from request.
    const sender = req.body['sender']

    // Compute the sponsor hash.
    const sponsorHash = tx.signingHash(sender)

    // Sponsor account (with money): 
    // 0x126cdb344f476f25b9fb2050513f425a82f71046
    const sponsorPriv = Buffer.from(
        '5df5e7f22a71dfd3d032ff5eb9dfc7dbe9c950e0671745826639a0423cd45d7f',
        'hex'
    )

    // Compute the sponsor signature with hash+private key.
    const signature = cry.secp256k1.sign(sponsorHash, sponsorPriv)

    // Send back the signature.
    res.send({
        'sponsor_signature': signature.toString('hex')
    })

})

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

The above code is quite simple, with some details to pay attention to:

  • The server is listening on localhost:3000.

  • The tx is re-constructed from the request, it’s a good time inspecting it.

  • The sponsor is using his own private key to sign.

  • The sponsor_signature is returned to the user.

Back to the User’s side

Finally, on the user’s side, it can assemble the final compound signature and post the transaction to the VeChain network!

// Fetch the sponsor signature.
const sponsorSignature = await getSponosrSignature(
    '0x'+originAddress.toString('hex'),
    txBody
)
    
// Compose a combined signature of user + sponsor.
const sig = Buffer.concat([
    originSignature,
    Buffer.from(sponsorSignature, 'hex')
])

// Mount on the combined signature.
tx.signature = sig

// Convert the tx to raw format.
const rawTx = '0x' + tx.encode().toString('hex')

// Submit the raw transaction by hand to the test-net.
const url = 'https://sync-testnet.vechain.org/transactions'
fetch(url, {
    method: 'POST',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({'raw': rawTx})
}).then(response => {
    response.text().then(r => {console.log(r)})
}).catch(err => {
    console.log('err', err)
})

The process is quite straightforward, concatenate of user’s signature originSignature and the sponsor’s signature sponsorSignature . Then finally call the POST method to send to our VeChain testnet.

An Example Result

As of writing, I have successfully posted several transactions and all show details of VIP-191 fee delegation feature, for example, the transaction with below ID:

As we can see from the above picture, the 26.64 VTHO is paid not by the user, but by the sponsor. Hence, the fee delegation is complete.

Conclusion

I hope you like this trilogy of tutorials on VIP-191 of VeChain. As always, may the force be with you!

Let’s continue where we left off from the :

Tx: 0xd8b94a68764f6f49eb33bb7a6e895e0f2565c8c8e1731f1258b188561b581e87 []

Example of VIP-191 Result

Due to the length of the article, this VIP-191 tutorial doesn’t show the full source code from the user’s side and the sponsor’s side. I have included a workable sample of and on Github for you to run.

LINK
2nd tutorial
Web Link
user.js
sponsor.js