CREC SDK Extension: DVP
A Go SDK extension for Delivery versus Payment (DvP) settlement operations on CREC. The DvP (Delivery vs. Payment) service allows for the secure and trustless transfer of assets between parties.
Installation
go get github.com/smartcontractkit/crec-sdk-ext-dvp
Overview
This extension provides utilities for preparing DvP (Delivery versus Payment) settlement operations, enabling atomic exchange of assets between counterparties on blockchain networks.
Features
- Propose settlements with optional token approvals or holds
- Accept and execute settlements
- Compute settlement hashes for verification
- Support for ERC20 and ERC3643 token types
- ISO 4217 currency code mapping
Usage
Basic Setup
import (
"github.com/smartcontractkit/crec-sdk-ext-dvp/operations"
)
ext, err := operations.New(&operations.Options{
CCIPDVPCoordinatorAddress: "0x...",
AccountAddress: "0x...",
})
if err != nil {
log.Fatal(err)
}
Proposing a Settlement
import (
"github.com/smartcontractkit/crec-sdk-ext-dvp/currency"
"github.com/smartcontractkit/crec-sdk-ext-dvp/events"
"github.com/ethereum/go-ethereum/common"
"math/big"
)
// Create settlement details
settlement := &events.Settlement{
SettlementId: big.NewInt(1),
PartyInfo: events.PartyInfo{
BuyerSourceAddress: common.HexToAddress("0xBuyer..."),
BuyerDestinationAddress: common.HexToAddress("0xBuyer..."),
SellerSourceAddress: common.HexToAddress("0xSeller..."),
SellerDestinationAddress: common.HexToAddress("0xSeller..."),
ExecutorAddress: common.HexToAddress("0xExecutor..."),
},
TokenInfo: events.TokenInfo{
PaymentTokenSourceAddress: common.HexToAddress("0xPaymentToken..."),
PaymentTokenDestinationAddress: common.HexToAddress("0xPaymentToken..."),
AssetTokenSourceAddress: common.HexToAddress("0xAssetToken..."),
AssetTokenDestinationAddress: common.HexToAddress("0xAssetToken..."),
PaymentTokenAmount: big.NewInt(1000000),
AssetTokenAmount: big.NewInt(1000000000000000000),
PaymentCurrency: currency.Map["USD"],
PaymentLockType: events.LockTypeERC20,
AssetLockType: events.LockTypeERC20,
},
DeliveryInfo: events.DeliveryInfo{
PaymentSourceChainSelector: uint64(1),
PaymentDestinationChainSelector: uint64(1),
AssetSourceChainSelector: uint64(1),
AssetDestinationChainSelector: uint64(1),
},
SecretHash: common.Hash{},
ExecuteAfter: big.NewInt(0),
Expiration: big.NewInt(9999999999),
CcipCallbackGasLimit: 0,
Data: []byte{},
}
// Option 1: Propose without token approval (assumes approval exists)
op, err := ext.PrepareProposeSettlementOperation(settlement)
// Option 2: Propose with automatic token approval
op, err := ext.PrepareProposeSettlementWithTokenApprovalOperation(settlement)
// Option 3: Propose with token hold (ERC3643 only)
op, err := ext.PrepareProposeSettlementWithTokenHoldOperation(settlement, holdManagerAddress)
Accepting a Settlement
settlementHash := common.HexToHash("0x...")
op, err := ext.PrepareAcceptSettlementOperation([32]byte(settlementHash))
Executing a Settlement
settlementHash := common.HexToHash("0x...")
op, err := ext.PrepareExecuteSettlementOperation([32]byte(settlementHash))
Computing Settlement Hash
hash, err := ext.HashSettlement(settlement)
fmt.Printf("Settlement hash: %s\n", hash.Hex())
Lock Types
| Constant |
Value |
Description |
LockTypeNone |
0 |
No lock type specified |
LockTypeERC20 |
1 |
Standard ERC20 token |
LockTypeERC3643 |
2 |
Security token (T-REX) |
Settlement Status
| Constant |
Value |
Description |
SettlementStatusNew |
0 |
Settlement created |
SettlementStatusOpen |
1 |
Settlement proposed |
SettlementStatusAccepted |
2 |
Settlement accepted |
SettlementStatusClosing |
3 |
Settlement in closing state |
SettlementStatusSettled |
4 |
Settlement completed |
SettlementStatusCanceled |
5 |
Settlement canceled |
Currency Codes
The currency package provides ISO 4217 currency codes for off-chain payment specifications:
import "github.com/smartcontractkit/crec-sdk-ext-dvp/currency"
usdCode := currency.Map["USD"] // Returns 147
Decoding Events
Decode typed events from raw CREC watcher events:
import dvp "github.com/smartcontractkit/crec-sdk-ext-dvp"
decoded, err := dvp.DecodeFromEvent(ctx, event)
switch decoded.EventName() {
case events.EventSettlementOpened:
ev := decoded.ConcreteEvent.(*events.SettlementOpened)
fmt.Printf("Settlement %s opened\n", ev.SettlementId)
case events.EventSettlementSettled:
ev := decoded.ConcreteEvent.(*events.SettlementSettled)
fmt.Printf("Settlement %s settled\n", ev.SettlementId)
}
License
MIT