Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 62 additions & 7 deletions application/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ package application
import (
"encoding/hex"
"encoding/json"
"math/big"
"strings"

"github.com/0xAtelerix/sdk/gosdk"
"github.com/0xAtelerix/sdk/gosdk/apptypes"
"github.com/0xAtelerix/sdk/gosdk/external"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/holiman/uint256"
"github.com/ledgerwatch/erigon-lib/kv"
)
Expand All @@ -17,11 +22,12 @@ func AccountKey(sender string, token string) []byte {
}

type Transaction[R Receipt] struct {
Sender string `json:"sender"`
Value uint64 `json:"value"`
Receiver string `json:"receiver"`
Token string `json:"token"`
TxHash string `json:"hash"`
Sender string `json:"sender"`
Value uint64 `json:"value"`
Receiver string `json:"receiver"`
Token string `json:"token"`
TxHash string `json:"hash"`
GenerateExtTxn bool `json:"generate_ext_txn,omitempty"` // When true, generates an external transaction to Sepolia
}

func (e *Transaction[R]) Unmarshal(b []byte) error {
Expand All @@ -33,7 +39,11 @@ func (e Transaction[R]) Marshal() ([]byte, error) {
}

func (e Transaction[R]) Hash() [32]byte {
txHash := strings.TrimPrefix(e.TxHash, "0x")
// Remove all hex prefixes (handles cases like "0x0x..." or "0X0x...")
txHash := e.TxHash
for strings.HasPrefix(strings.ToLower(txHash), "0x") {
txHash = txHash[2:]
}

hashBytes, err := hex.DecodeString(txHash)
if err != nil {
Expand Down Expand Up @@ -98,7 +108,20 @@ func (e Transaction[R]) Process(

res = e.successReceipt(senderBalance, receiverBalance)

return res, []apptypes.ExternalTransaction{}, nil
// Generate external transaction if requested
var externalTxs []apptypes.ExternalTransaction

if e.GenerateExtTxn {
extTx, err := e.createExternalTransaction()
if err != nil {
// Log error but don't fail the transaction
return e.failedReceipt(err), nil, nil
}

externalTxs = append(externalTxs, extTx)
}

return res, externalTxs, nil
}

func (e *Transaction[R]) failedReceipt(err error) R {
Expand All @@ -125,3 +148,35 @@ func (e *Transaction[R]) successReceipt(senderBalance, receiverBalance *uint256.
TxStatus: apptypes.ReceiptConfirmed,
}
}

// createExternalTransaction creates an external transaction to Sepolia
// with a payload that matches the AppChain contract format
func (e *Transaction[R]) createExternalTransaction() (apptypes.ExternalTransaction, error) {
// Parse receiver as Ethereum address
// If it's not a valid address, create a deterministic address from the string
var recipientAddr common.Address
if common.IsHexAddress(e.Receiver) {
recipientAddr = common.HexToAddress(e.Receiver)
} else {
// For non-address receivers (like "alice", "bob"), create a deterministic address
// by hashing the name using Keccak256 and taking the last 20 bytes
hash := crypto.Keccak256Hash([]byte(e.Receiver))
recipientAddr = common.BytesToAddress(hash.Bytes())
}

// Convert value to big.Int
amount := big.NewInt(int64(e.Value))

// Create payload matching AppChain contract format using the existing function
// Format: [recipient:20bytes][amount:32bytes][tokenName:variable]
// This matches the contract in 0xAtelerix/sdk/contracts/pelacli/AppChain.sol
payload := createTokenMintPayload(recipientAddr, amount, e.Token)

// Create external transaction targeting Sepolia
extTx, err := external.NewExTxBuilder(payload, gosdk.EthereumSepoliaChainID).Build()
if err != nil {
return apptypes.ExternalTransaction{}, err
}

return extTx, nil
}
18 changes: 16 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ services:
volumes:
- ./pelacli_data:/consensus_data
- ./app_data:/data
- ./config/chain_data.json:/data/chain_data.json:ro
- ./config/chain_data.json:/config/chain_data.json:ro
- ./multichain:/multichain
ports:
- "9090:9090"
Expand All @@ -22,7 +22,7 @@ services:
- --stream-dir=/consensus_data/events
- --tx-dir=/consensus_data/fetcher/snapshots/42
- --rpc-port=:8080
- --multichain-config=/data/chain_data.json
- --multichain-config=/config/chain_data.json

pelacli:
container_name: pelacli
Expand All @@ -32,6 +32,8 @@ services:
- ./config/consensus_chains.json:/consensus_chains.json:ro
- ./config/ext_networks.json:/ext_networks.json:ro
- ./multichain:/multichain
ports:
- "8081:8081"
command:
- consensus
- --snapshot-dir=/consensus_data
Expand All @@ -40,4 +42,16 @@ services:
- --multichain-dir=/consensus_data/multichain_db
- --chains-json=/consensus_chains.json
- --ext-txn-config-json=/ext_networks.json
- --api-port=8081

explorer:
image: pelagosnetwork/explorer:latest
ports:
- "3000:3000"
environment:
- RPC_URL=http://localhost:8080/rpc
- EXTERNAL_RPC_URL=http://localhost:8081/rpc
depends_on:
- appchain
- pelacli

Loading