Skip to content

Commit

Permalink
Merge branch 'main' of github.com:sygmaprotocol/sygma-sdk into feat/e…
Browse files Browse the repository at this point in the history
…rc20-generic-handler
  • Loading branch information
saadahmsiddiqui committed Sep 9, 2024
2 parents c8081a9 + 002163d commit 4ec8bb7
Show file tree
Hide file tree
Showing 59 changed files with 2,143 additions and 80 deletions.
62 changes: 62 additions & 0 deletions .github/workflows/release-bitcoin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Publish Sygma SDK Bitcoin package to GitHub Package Registry

on:
push:
branches: ["main"]
paths: ["packages/bitcoin/**"]

jobs:
maybe-release:
name: release
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
# you should probably do this after your regular CI checks passes
# it will analyze commits and create PR with new version and updated CHANGELOG:md file. On merging it will create github release page with changelog
- uses: google-github-actions/release-please-action@v3
id: release
with:
command: manifest
release-type: node
token: ${{secrets.RELEASE_TOKEN}}
config-file: "release-please/rp-bitcoin-config.json"
manifest-file: "release-please/rp-bitcoin-manifest.json"
monorepo-tags: true
default-branch: main
path: "packages/bitcoin"
changelog-types: '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false},{"type":"revert","hidden":true}]'

- uses: actions/checkout@v4
# these if statements ensure that a publication only occurs when
# a new release is created:
if: ${{ steps.release.outputs.releases_created }}

- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: 18
registry-url: "https://registry.npmjs.org"
scope: "@buildwithsygma"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
if: ${{ steps.release.outputs.releases_created }}

- name: Enable corepack
run: corepack enable
if: ${{ steps.release.outputs.releases_created }}

- name: Install dependencies
run: yarn install --immutable
if: ${{ steps.release.outputs.releases_created }}

- run: yarn build
if: ${{ steps.release.outputs.releases_created }}

- env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
if: ${{ steps.release.outputs.releases_created }}
run: |
echo -e "\nnpmAuthToken: \"$NODE_AUTH_TOKEN\"" >> ./.yarnrc.yml
- run: yarn workspace @buildwithsygma/bitcoin npm publish --access public
if: ${{ steps.release.outputs.releases_created }}
10 changes: 10 additions & 0 deletions examples/bitcoin-to-evm-fungible-transfer/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SYGMA_ENV=testnet
BLOCKSTREAM_URL="your blockstream url"
DESTINATION_ADDRESS="your evm destination address"
RESOURCE_ID="resource id"
SOURCE_CAIPID="source domain caip id"
EXPLORER_URL="your bitcoin explorer url"
MNEMONIC="your 12 or 24 mnemonic"
DERIVATION_PATH="your derivation path"
ADDRESS="your bitcoin address to use and send change"
AMOUNT="your amount to transfer"
122 changes: 122 additions & 0 deletions examples/bitcoin-to-evm-fungible-transfer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Sygma SDK Bitcoin to EVM example

## Sygma SDK ERC20 Example

This is an example that demonstrates functionality of the protocol using Sygma SDK. The src/transfer.ts script showcases how bitcoins can transferred over to an EVM Sepolia address utilizing `@buildwithsygma/bitcoin` package.

## Prerequisites

Before running the script, ensure that you have the following:

- Node.js
- Yarn (version 3.4.1 or higher)
- A development wallet with some testnet BTC
- The private key of a Taproot address to sign the transaction
- Valid UTXO information of your taproot address. You can get the UTXO's of your address by querying some public APIS like blockstream one and passing your address as parameter

## Getting started

### 1. Clone the repository

To get started, clone this repository to your local machine with:

```bash
git clone [email protected]:sygmaprotocol/sygma-sdk.git
cd sygma-sdk/
```

### 2. Install dependencies

Install the project dependencies by running:

```bash
yarn install
```

### 3. Build the sdk

To start the example you need to build the sdk first with:

```bash
yarn build:all
```

## Usage

This example uses the `dotenv` module to manage private keys and also to define env variables needed for this example to work. To run the example, you will need to configure your environment variables A `.env.sample` is provided as a template.

**DO NOT COMMIT PRIVATE KEYS WITH REAL FUNDS TO GITHUB. DOING SO COULD RESULT IN COMPLETE LOSS OF YOUR FUNDS.**

Create a `.env` file in the btc-to-evm example folder:

```bash
cd examples/btc-to-evm-fungible-transfer
touch .env
```

Replace the values that are defined in the `.env.sample` file:

```bash
SYGMA_ENV=testnet
BLOCKSTREAM_URL="your blockstream url"
DESTINATION_ADDRESS="your evm destination address"
DESTINATION_CHAIN_ID="destination domain chain id"
RESOURCE_ID="resource id"
SOURCE_CAIPID="source domain caip id"
EXPLORER_URL="your bitcoin explorer url"
MNEMONIC="your 12 or 24 mnemonic"
DERIVATION_PATH="your derivation path"
ADDRESS="your change address"
AMOUNT="your amount to transfer"
```

* `DESTINATION_ADDRESS`: your `evm` destination address where you want your funds to be relayed
* `DESTINATION_CHAIN_ID`: this is the chainId of the network where you want to receive the funds
* `RESOURCE_ID`: the bitcoin resource id that can be found in our `shared-config` repository
* `SOURCE_CAIPID`: caipId of the bitcoin domain
* `MNEMONIC`: your testnet wallet mnemonic
* `DERIVATION_PATH`: derivation path for your mnemonic. Use derivation path for either P2TR address or P2WPKH one
* `ADDRESS`: the address from which we get the UTXO's and to which we send the change
* `AMOUNT`: the actual amount to transfer

Take into consideration that a typical response when query the utxos of your address look like this:

```json
{
"txid": "7bdf2ce472ee3c9cba6d2944b0ca6bcdceb4b893c7d2163678a0b688a8315d74",
"vout": 3,
"status": {
"confirmed": true,
"block_height": 2869535,
"block_hash": "",
"block_time": 1721666904
},
"value": 936396
}
```

Where `value` is the amount you have at your disposal and `vout` is the transaction output index.

To send Testnet BTC to your EVM account on Sepolia using Taproot address run:

```bash
yarn run transfer:p2tr
```

To send Testnet BTC to your EVM account on Sepolia using P2WPKH address run:

```bash
yarn run transfer:p2wpkh
```

Replace the placeholder values in the `.env` file with your own Testnet BTC Taproot private key as well as the other env variables needed such as DESTINATION_ADDRESS, DESTINATION_DOMAIN_ID, RESOURCE_ID, DERIVATION_PATH, and SOURCE_DOMAIN_ID.

## Script Functionality

This example script performs the following steps:
- I creates a signer to sign the Bitcoin Testnet transaction using your provider private key from your taproot address.
- it gets the fee for 5 confirmations blocks. You can change that following this [reference](https://github.com/Blockstream/esplora/blob/master/API.md#get-fee-estimates)
- it then encodes the provided EVM address + the destination domain id needed to relay the funds
- Once you have provided with the UTXO information needed, it will calculate the fee of the transaction based on some aproximation value
- it then instantiate a PSBT class to be able to provide the inputs and outputs needed to relay the assets
- It signs the transaction and the broadcasted into the Bitcoin testnet network. You will get an url with the transaction id to follow the confirmation of the transaction.
42 changes: 42 additions & 0 deletions examples/bitcoin-to-evm-fungible-transfer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@buildwithsygma/sygma-sdk-bitcoin-to-evm-fungible-transfer-example",
"version": "0.1.0",
"type": "module",
"description": "Sygma sdk examples",
"sideEffects": false,
"repository": {
"type": "git",
"url": "https://github.com/sygmaprotocol/sygma-sdk"
},
"keywords": [
"sygma",
"sygmaprotocol",
"buildwithsygma",
"web3",
"bridge",
"bitcoin"
],
"scripts": {
"transfer:p2tr": "tsx src/transfer.p2tr.ts",
"transfer:p2wpkh": "tsx src/transfer.p2wpkh.ts"
},
"author": "Sygmaprotocol Product Team",
"license": "LGPL-3.0-or-later",
"devDependencies": {
"dotenv": "^16.3.1",
"eslint": "8",
"ts-node": "10.9.1",
"typescript": "5.0.4"
},
"dependencies": {
"@buildwithsygma/bitcoin": "workspace:^",
"@buildwithsygma/core": "workspace:^",
"@buildwithsygma/utils": "workspace:^",
"bip32": "^4.0.0",
"bip39": "^3.1.0",
"bitcoinjs-lib": "^6.1.6",
"ecpair": "^2.1.0",
"tiny-secp256k1": "^2.2.3",
"tsx": "^4.15.4"
}
}
85 changes: 85 additions & 0 deletions examples/bitcoin-to-evm-fungible-transfer/src/blockstreamApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { TypeOfAddress } from "@buildwithsygma/bitcoin";
import type { BitcoinTransferParams } from "@buildwithsygma/bitcoin";
import type { Network, Signer } from "bitcoinjs-lib";
import { payments, Psbt } from "bitcoinjs-lib";

type SizeCalculationParams = {
utxoData: BitcoinTransferParams["utxoData"];
network: Network;
publicKey: Buffer;
depositAddress: string;
domainId: number;
amount: bigint;
feeValue: bigint;
changeAddress: string;
signer: Signer;
typeOfAddress: TypeOfAddress;
};

/**
* Ee calculate the size of the transaction by using a tx with zero fee => input amount == output amount
* Correctnes of the data is not relevant here, we need to know what's the size is going to be for the amount of inputs passed and the 4 outputs (deposit, change, fee, encoded data) we use to relay the funds
*/
export const calculateSize = ({
utxoData,
network,
publicKey,
depositAddress,
domainId,
amount,
feeValue,
changeAddress,
signer,
typeOfAddress,
}: SizeCalculationParams): number => {
const pstb = new Psbt({ network: network });

const scriptPubKey: Buffer = (typeOfAddress !== TypeOfAddress.P2TR)
? payments.p2wpkh({ pubkey: publicKey, network: network }).output as Buffer
: payments.p2tr({ internalPubkey: publicKey, network: network }).output as Buffer;

utxoData.forEach((utxo) => {
const input = {
hash: utxo.utxoTxId,
index: utxo.utxoOutputIndex,
witnessUtxo: {
value: Number(utxo.utxoAmount),
script: scriptPubKey,
},
};

if (typeOfAddress === TypeOfAddress.P2TR) {
(input as any).tapInternalKey = publicKey;
}

pstb.addInput(input);
});


const outputs = [
{
script: payments.embed({
data: [Buffer.from(`${depositAddress}_${domainId}`)],
}).output as Buffer,
value: 0,
},
{
address: changeAddress,
value: Number(amount),
},
{
address: changeAddress,
value: Number(feeValue),
},
{
address: changeAddress,
value: 0,
}
];

outputs.forEach(output => pstb.addOutput(output));

pstb.signAllInputs(signer);
pstb.finalizeAllInputs();
return pstb.extractTransaction(true).virtualSize();
};
Loading

0 comments on commit 4ec8bb7

Please sign in to comment.