Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tx manager: staking on-chain interaction #34

Merged
merged 4 commits into from
Jan 8, 2024
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
39 changes: 36 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ You may learn background information on various components of the exchange

#### [Publisher Guide](docs/publisher_guide.md)

#### [On-Chain Guide](docs/onchain_guide.md)

## Contributing

We welcome and appreciate your contributions! Please see the [Contributor Guide](/CONTRIBUTING.md), [Code Of Conduct](/CODE_OF_CONDUCT.md) and [Security Notes](/SECURITY.md) for this repository.
File renamed without changes.
3 changes: 2 additions & 1 deletion docs/client_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ After determining the subfile CID, client should supply a local path for writing
--free-query-auth-token 'Bearer imfreeee' \
--mnemonic "sheriff obscure trick beauty army fat wink legal flee leader section suit" \
--chain-id 421614 \
--verifier 0xfC24cE7a4428A6B89B52645243662A02BA734ECF
--verifier 0xfC24cE7a4428A6B89B52645243662A02BA734ECF \
--provider [arbitrum-sepolia-rpc-endpoint]
```


Expand Down
74 changes: 74 additions & 0 deletions docs/onchain_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# On-Chain Subcommand Documentation

The subcommand `wallet` is designed to facilitate various on-chain actions through a command-line interface. This guide focuses on how users can perform wallet transactions on the blockchain.

## Configuration

Before starting, ensure you have set up the following:

- **Mnemonic**: A secret phrase (mnemonic) for accessing your wallet.
- **Provider URL**: The endpoint URL of your blockchain provider.

## Usage

To use the Wallet CLI, the following subcommands and options are available:

### Global Options

- `--mnemonic KEY`: Sets the mnemonic for the wallet. This is required for any wallet operations.
- `--provider provider_url`: The blockchain provider endpoint URL.

### Subcommands

- `allocate`: Allocate funds for a specific purpose.
- `unallocate`: Revoke previously allocated funds.

#### Allocate

To open allocation towards a deployment, provide the deployment IPFS hash, the token amount, the current epoch number (should later be resolved automaically), and fill in the `allocate` subcommand with the necessary arguments:

```shell
✗ subfile-exchange wallet \
--mnemonic <mnemonic> \
--provider <provider_url> \
allocate \
--tokens <tokens> \
--deployment-ipfs <deployment_ipfs> \
--epoch <epoch>
```

#### Unallocate

>To be implemented

### Examples

**Allocating Funds:**

```shell
✗ cargo run -p subfile-exchange wallet \
--mnemonic "mnemonic phrase" \
--provider "http://localhost:8545" \
allocate \
--tokens 100 \
--deployment-ipfs QmeaPp764FjQjPB66M9ijmQKmLhwBpHQhA7dEbH2FA1j3v \
--epoch 100
```

- Replace placeholders like `"your mnemonic"`, `"http://localhost:8545"`, `"0x123..."`, `"QmHash"`, etc., with actual values.
- Ensure that the mnemonic and provider URL are kept secure and private.

With RUST_LOG turned on, you can expect the following logs upon success
```
2024-01-08T18:17:34.123941Z INFO subfile_exchange::transaction_manager: Initialize transaction manager
at subfile-exchange/src/transaction_manager/mod.rs:32

2024-01-08T18:17:34.650044Z INFO subfile_exchange::transaction_manager::staking: allocate params, dep_bytes: [241, 64, 71, 78, 218, 63, 159, 91, 130, 173, 178, 168, 30, 254, 183, 20, 225, 131, 35, 230, 52, 85, 74, 196, 40, 255, 173, 61, 144, 126, 223, 33], tokens: Some(Allocate(AllocateArgs { tokens: 256, deployment_ipfs: "QmeaPp764FjQjPB66M9ijmQKmLhwBpHQhA7dEbH2FA1j3v", epoch: 101 })), allocation_id: 0x75e11e0f2319913c28d0b1916b4b1d9a1ac3977b, metadata: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], proof: Bytes(0xac1b36d68ea95ebe9f9793850cf083a031d40806121dc2dac525423c50611d18053f195627f6bffe036b9325b4dfd273959457b5d3f1c1b53095c096182756bb1b)
at subfile-exchange/src/transaction_manager/staking.rs:67

2024-01-08T18:17:34.765769Z DEBUG subfile_exchange::transaction_manager::staking: estimate gas, estimated_gas: 379109
at subfile-exchange/src/transaction_manager/staking.rs:82

2024-01-08T18:17:42.224872Z INFO subfile_exchange: Allocation transaction finished, allocation_id: 0x75e11e0f2319913c28d0b1916b4b1d9a1ac3977b, tx_receipt: Some(TransactionReceipt { transaction_hash: 0x835b790326abf1555545920265e54d5bfbaba150aef31820529736e6727c7a0a, ... })
at subfile-exchange/src/main.rs:75
```
4 changes: 3 additions & 1 deletion subfile-exchange/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ path = "src/main.rs"
alloy-sol-types = { version = "0.5.0", features = ["eip712-serde"] }
alloy-primitives = { version = "0.5.0", features = ["serde"] }
anyhow = "1.0"
bs58 = "0.5.0"
base64 = "0.21"
build-info = "0.0.34"
bytes = "1.0"
Expand All @@ -28,6 +29,7 @@ ethers = "2.0.11"
# ethers = {version = "2.0.11", features = [ "abigen-online" ]}
ethers-core = "2.0.11"
futures = { version = "0.3", features = ["compat"] }
hdwallet = "0.4.1"
hex = "0.4.3"
http = "0.2"
hyper = { version = "0.14.27", features = [ "server" ]}
Expand All @@ -43,7 +45,7 @@ secp256k1 = "0.28.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.9"
sha2 = "0.10.8"
sha2 = "0.10"
tap_core = { version = "0.7.0", git = "https://github.com/semiotic-ai/timeline-aggregation-protocol" }
tempfile = "3.2.0"
tokio = { version = "1.28", features = ["time", "sync", "macros", "test-util", "rt-multi-thread"] }
Expand Down
132 changes: 84 additions & 48 deletions subfile-exchange/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use clap::{arg, ValueEnum};
use clap::{command, Args, Parser, Subcommand};
use ethers_core::types::U256;
use serde::{Deserialize, Serialize};
use std::fmt;

use tracing::subscriber::SetGlobalDefaultError;
use tracing_subscriber::EnvFilter;
use tracing_subscriber::FmtSubscriber;

use crate::util::parse_key;

#[derive(Clone, Debug, Parser, Serialize, Deserialize)]
#[command(
name = "subfile-exchange",
Expand Down Expand Up @@ -51,67 +54,55 @@ impl Cli {
pub enum Role {
Downloader(DownloaderArgs),
Publisher(PublisherArgs),
Server(ServerArgs),
Wallet(WalletArgs),
}

/// Server enable payments through the staking contract,
/// assume indexer is already registered on the staking registry contract
///1. `allocate` - indexer address, Qm hash in bytes32, token amount, allocation_id, metadata: utils.hexlify(Array(32).fill(0)), allocation_id_proof
///2. `close_allocate` -allocationID: String, poi: BytesLike (0x0 32bytes)
///3. `close_allocate` and then `allocate`
/// receipt validation and storage is handled by the indexer-service framework
/// receipt redemption is handled by indexer-agent
///
/// Client payments - assume client signer is valid (should work without gateways)
///1. `deposit` - to a sender address and an amount
///2. `depositMany` - to Vec<sender address, an amount>
#[derive(Clone, Debug, Subcommand, Serialize, Deserialize)]
#[group(required = false, multiple = true)]
pub enum OnchainAction {
Allocate(AllocateArgs),
Unallocate(UnallocateArgs),
}

#[derive(Clone, Debug, Args, Serialize, Deserialize, Default)]
#[group(required = false, multiple = true)]
pub struct ServerArgs {
#[arg(
long,
value_name = "HOST",
default_value = "127.0.0.1",
env = "HOST",
help = "Subfile server host"
)]
pub host: String,
#[arg(
long,
value_name = "PORT",
default_value = "5678",
env = "PORT",
help = "Subfile server port"
)]
pub port: usize,
// Taking from config right now, later can read from DB table for managing server states
#[arg(
long,
value_name = "SUBFILES",
env = "SUBFILES",
value_delimiter = ',',
help = "Comma separated list of IPFS hashes and local location of the subfiles to serve upon start-up; format: [ipfs_hash:local_path]"
)]
pub subfiles: Vec<String>,
pub struct WalletArgs {
#[clap(subcommand)]
pub action: Option<OnchainAction>,
#[clap(
long,
value_name = "free-query-auth-token",
env = "FREE_QUERY_AUTH_TOKEN",
help = "Auth token that clients can use to query for free"
value_name = "KEY",
value_parser = parse_key,
env = "MNEMONIC",
hide_env_values = true,
help = "Mnemonic to the Indexer operator wallet (first address of the wallet is used",
)]
pub free_query_auth_token: Option<String>,
pub mnemonic: String,
#[clap(
long,
value_name = "admin-auth-token",
env = "ADMIN_AUTH_TOKEN",
help = "Admin Auth token for server management"
value_name = "provider_url",
env = "PROVIDER",
help = "Blockchain provider endpoint"
)]
pub admin_auth_token: Option<String>,
pub provider: String,
#[clap(
long,
value_name = "mnemonic",
env = "MNEMONIC",
help = "Mnemonic for the operator wallet"
)]
pub mnemonic: String,
//TODO: More complex price management
#[arg(
long,
value_name = "PRICE_PER_BYTE",
default_value = "1",
env = "PRICE_PER_BYTE",
help = "Price per byte; price do not currently have a unit, perhaps use DAI or GRT, refer to TAP"
value_name = "verifier",
env = "VERIFIER",
help = "TAP verifier contract address"
)]
pub price_per_byte: f32,
pub verifier: Option<String>,
}

#[derive(Clone, Debug, Args, Serialize, Deserialize, Default)]
Expand Down Expand Up @@ -315,6 +306,51 @@ pub struct PublisherArgs {
pub chain_id: String,
}

#[derive(Clone, Debug, Args, Serialize, Deserialize, Default)]
#[group(required = false, multiple = true)]
pub struct AllocateArgs {
#[clap(
long,
value_name = "tokens",
env = "TOKENS",
help = "Token amount to allocate"
)]
pub tokens: U256,
#[clap(
long,
value_name = "deployment_ipfs",
env = "DEPLOYMENT_IPFS",
help = "Deployment IPFS hash to allocate"
)]
pub deployment_ipfs: String,
#[clap(
long,
value_name = "epoch",
env = "EPOCH",
help = "Epoch field to generate unique allocation id (Should be auto-resolve through network query)"
)]
pub epoch: u64,
}

#[derive(Clone, Debug, Args, Serialize, Deserialize, Default)]
#[group(required = false, multiple = true)]
pub struct UnallocateArgs {
#[clap(
long,
value_name = "deployment_ipfs",
env = "DEPLOYMENT_IPFS",
help = "Deployment IPFS hash to unallocate"
)]
pub deployment_ipfs: String,
#[clap(
long,
value_name = "allocation_id",
env = "ALLOCATION_ID",
help = "Deployment IPFS hash to unallocate"
)]
pub allocation_id: String,
}

#[allow(unused)]
#[derive(ValueEnum, Clone, Debug, Serialize, Deserialize, Default)]
pub enum FileType {
Expand Down
2 changes: 2 additions & 0 deletions subfile-exchange/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum Error {
InvalidPriceFormat(String),
ContractError(String),
ObjectStoreError(object_store::Error),
WalletError(ethers::signers::WalletError),
}

impl fmt::Display for Error {
Expand All @@ -35,6 +36,7 @@ impl fmt::Display for Error {
Error::InvalidPriceFormat(ref msg) => write!(f, "Price format error: {}", msg),
Error::ContractError(ref msg) => write!(f, "Contract call error: {}", msg),
Error::ObjectStoreError(ref err) => write!(f, "Object store error: {}", err),
Error::WalletError(ref err) => write!(f, "Wallet error: {}", err),
}
}
}
Expand Down
Loading