Submit intent
This example demonstrates how to submit an intent using the bloXroute Gateway gRPC API.
Name: SubmitIntent
SubmitIntent
is a GRPC method that propagates intent to the BDN.
SubmitIntentRequest
arguments:
Key | Description | Values |
---|---|---|
| ETH address of the DApp that should receive solution for this intent |
|
| ETH address of the intent sender |
|
| intent payload |
|
| Keccak256Hash of the intent payload |
|
| ECDSA signature of the hash |
|
SubmitIntentReply
fields:
Key | Description | Values |
---|---|---|
| UUID of the intent |
|
| timestamp when intent was first seen in BDN (for now empty) |
|
Examples - gRPC
package main
import (
"context"
"fmt"
"log"
pb "github.com/bloXroute-Labs/gateway/v2/protobuf"
"github.com/ethereum/go-ethereum/crypto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
// gatewayHost is the address of the gateway to which the intent is being submitted
const gatewayHost = "127.0.0.1:5002"
// authHeader is the authorization header of your BloxRoute Account
const authHeader = "<YOUR-AUTHORIZATION-HEADER>"
func main() {
// this will use localhost CA to verify the certificate
creds := credentials.NewClientTLSFromCert(nil, "")
// Dial the gateway
conn, err := grpc.Dial(gatewayHost,
grpc.WithTransportCredentials(creds),
grpc.WithPerRPCCredentials(blxrCredentials{authorization: authHeader}))
if err != nil {
log.Fatalln("dial grpc", err)
}
// Create a client
client := pb.NewGatewayClient(conn)
// Generate the intent
intentRequest := genSubmitIntent()
// Submit the intent
resp, err := client.SubmitIntent(context.Background(), intentRequest)
if err != nil {
log.Fatalln(err)
}
fmt.Printf("done submitting intent to %s\nsender_addr: %s\nintent_id: %s\n", gatewayHost, intentRequest.SenderAddress, resp.IntentId)
}
func genSenderCreds(intent []byte) (string, []byte, []byte) {
// Here we use a sample private key of sender to sign the intent
privateKeyHex := "4f3edf983ac636a65a842ce7c7aad7b7e3b1f6f6d1a91c37b1b39ce334b25554"
// Convert the hex string to a private key
privKey, err := crypto.HexToECDSA(privateKeyHex)
if err != nil {
log.Fatalln("error converting hex to ECDSA", err)
}
pubKey := privKey.PublicKey // extract the public key
signerAddress := crypto.PubkeyToAddress(pubKey) // extract the address
hash := crypto.Keccak256Hash(intent).Bytes() // need a hash to sign, so we're hashing the payload here
sig, err := crypto.Sign(hash, privKey) // sign the hash with the private key
if err != nil {
log.Fatalln("error signing with private key", err)
}
return signerAddress.String(), hash, sig
}
func getDAppAddress() string {
// The address of the DApp.
// Only the DApp with the correct private key can then receive the solution for the intent.
const dAppPrivateKeyHex = "7c4a8d09ca3762af61e59520943dc26494f8941e6e5b998321d3e84b8e4d3c16"
// Convert the hex string to a private key
dAppPrivKey, err := crypto.HexToECDSA(dAppPrivateKeyHex)
if err != nil {
log.Fatalln("error converting hex to ECDSA", err)
}
// Extract the public key
dAppPubKey := dAppPrivKey.PublicKey
dappAddress := crypto.PubkeyToAddress(dAppPubKey)
return dappAddress.String()
}
func genSubmitIntent() *pb.SubmitIntentRequest {
// The address of the DApp.
dappAddress := getDAppAddress()
// The intent to be submitted as a byte slice.
// This is a sample intent, and you should replace it with your own intent.
intent := []byte("i am intent")
// Sign the intent with the private key of the sender.
senderAddress, senderHash, senderSig := genSenderCreds(intent)
// Return the intent request
return &pb.SubmitIntentRequest{
DappAddress: dappAddress,
SenderAddress: senderAddress,
Intent: intent,
Hash: senderHash,
Signature: senderSig,
}
}
// blxrCredentials is a struct that implements the PerRPCCredentials interface
type blxrCredentials struct {
authorization string
}
// GetRequestMetadata is a method of the PerRPCCredentials interface
func (bc blxrCredentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
return map[string]string{
"authorization": bc.authorization,
}, nil
}
// RequireTransportSecurity is a method of the PerRPCCredentials interface
func (bc blxrCredentials) RequireTransportSecurity() bool {
return false
}
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/ethereum/go-ethereum/crypto"
"github.com/gorilla/websocket"
)
func main() {
dialer := websocket.DefaultDialer
// Add the following lines if you work with IP instead of DNS
// tlsConfig := &tls.Config{
// Certificates: []tls.Certificate{cert},
// InsecureSkipVerify: true,
// }
// dialer.TLSClientConfig = tlsConfig
req := genSubmitIntent()
wsSubscriber, _, err := dialer.Dial("wss://virginia.eth.blxrbdn.com/ws", http.Header{"Authorization": []string{"YOUR-AUTHORIZATION-HEADER"}})
if err != nil {
fmt.Println(err)
return
}
err = wsSubscriber.WriteMessage(websocket.TextMessage, req)
if err != nil {
fmt.Println(err)
return
}
for {
_, nextNotification, err := wsSubscriber.ReadMessage()
if err != nil {
fmt.Println(err)
}
fmt.Println(string(nextNotification)) // or process it generally
}
}
func genSubmitIntent() []byte {
// The address of the DApp.
dappAddress := getDAppAddress()
// The intent to be submitted as a byte slice.
// This is a sample intent, and you should replace it with your own intent.
intent := []byte("i am intent")
// Sign the intent with the private key of the sender.
senderAddress, senderHash, senderSig := genSenderCreds(intent)
m := map[string]interface{}{
"dapp_address": dappAddress,
"sender_address": senderAddress,
"intent": intent,
"hash": senderHash,
"signature": senderSig,
}
req, err := json.Marshal(m)
if err != nil {
log.Fatalln("marshal", err)
}
return []byte(fmt.Sprintf(`{"id": "1", "method": "blxr_submit_intent", "params": %s}`, req))
}
func getDAppAddress() string {
// The address of the DApp.
// Only the DApp with the correct private key can then receive the solution for the intent.
const dAppPrivateKeyHex = "7c4a8d09ca3762af61e59520943dc26494f8941e6e5b998321d3e84b8e4d3c16"
// Convert the hex string to a private key
dAppPrivKey, err := crypto.HexToECDSA(dAppPrivateKeyHex)
if err != nil {
log.Fatalln("error converting hex to ECDSA", err)
}
// Extract the public key
dAppPubKey := dAppPrivKey.PublicKey
dappAddress := crypto.PubkeyToAddress(dAppPubKey)
return dappAddress.String()
}
func genSenderCreds(intent []byte) (string, []byte, []byte) {
// Here we use a sample private key of sender to sign the intent
privateKeyHex := "4f3edf983ac636a65a842ce7c7aad7b7e3b1f6f6d1a91c37b1b39ce334b25554"
// Convert the hex string to a private key
privKey, err := crypto.HexToECDSA(privateKeyHex)
if err != nil {
log.Fatalln("error converting hex to ECDSA", err)
}
pubKey := privKey.PublicKey // extract the public key
signerAddress := crypto.PubkeyToAddress(pubKey) // extract the address
hash := crypto.Keccak256Hash(intent).Bytes() // need a hash to sign, so we're hashing the payload here
sig, err := crypto.Sign(hash, privKey) // sign the hash with the private key
if err != nil {
log.Fatalln("error signing with private key", err)
}
return signerAddress.String(), hash, sig
}
Last updated