Milestone 1 — User account management & repo management & mnemonic management & Transfer contract
User management, create an NEAR account for each developer
We will provide login function, you can login our website using Github, and we will create a NEAR account for each user by default
Repo & webhook management
We will fetch your GitHub repo list, so you can activate the repo you want to integrate with NEAR, the webhook module will listen to the pay event and trigger the transform module to pay developer NEAR
Address binding
/bytepay bind near 5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE
Recharge management
Withdraw the NEAR from our platform to developer's own wallet, if the developer bind its own address, payment will be transferred to the account directly
Transfer contract
We will provide a contract, provide transfer limit, whitelist, and transfer function.
config env
Near cli : https://gist.github.com/think-in-universe/019671d56a949ec8a475126f22d21248
export NEAR_CLI_MAINNET_RPC_SERVER_URL=https://public-rpc.blockpi.io/http/near
export NEAR_ENV=mainnet
near deploy --accountId ff3e8979eb1eac55858651bb40e51760bdfcf12ef57b1edbdd75f53fb0ed6c06 --wasmFile ./build/bytepay_contract_near.wasm
Near cli : https://gist.github.com/think-in-universe/019671d56a949ec8a475126f22d21248
export NEAR_CLI_TESTNET_RPC_SERVER_URL=https://public-rpc.blockpi.io/http/near-testnet
export NEAR_ENV=testnet
near deploy --accountId lafyun.testnet --wasmFile ./build/bytepay_contract_near.wasm
contract code
pub mod bytepay_near {
use near_sdk::{AccountId, Balance, env, log, near_bindgen, Promise};
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::collections::LookupMap;
near_sdk::setup_alloc!();
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct BytePayNearContract {
pub owner: AccountId,
pub balances: LookupMap<AccountId, Balance>,
pub whitelist: LookupMap<(AccountId, AccountId), Balance>,
}
impl Default for BytePayNearContract {
fn default() -> Self {
Self {
owner: env::current_account_id(),
balances: LookupMap::new(b"b".to_vec()),
whitelist: LookupMap::new(b"w".to_vec()),
}
}
}
#[near_bindgen]
impl BytePayNearContract {
pub fn get_owner(&self) -> AccountId {
self.owner.clone()
}
pub fn get_balance(&self, account: &AccountId) -> Option<Balance> {
self.balances.get(&account)
}
pub fn get_whitelist(&self, current: AccountId, account: AccountId) -> Option<Balance> {
self.whitelist.get(&(current, account))
}
pub fn recharge(&mut self, amount: Balance) -> &'static str {
let signer_account = env::signer_account_id();
let balance = self.balances.get(&signer_account).unwrap_or_default();
Promise::new(env::current_account_id()).transfer(amount);
self.balances.insert(&signer_account, &(amount + balance));
"END"
}
pub fn set_whitelist(&mut self, account: AccountId, amount: Balance) -> &'static str {
let signer_account = env::signer_account_id();
let balances = self.balances.get(&signer_account).unwrap_or_default();
if amount > balances {
log!("INSUFFICIENT_BALANCE");
return "INSUFFICIENT_BALANCE";
}
let key = (signer_account, account);
let old = self.whitelist.get(&key).unwrap_or_default();
self.whitelist.insert(&key, &(old + amount));
"END"
}
pub fn transfer(&mut self, from: AccountId, to: AccountId, amount: Balance) -> &'static str {
let call = env::signer_account_id();
let current = env::current_account_id();
if call != current {
log!("PERMISSION_DENIED");
return "PERMISSION_DENIED";
}
let key = (from.clone(), to.clone());
let limit = self.whitelist.get(&key).unwrap_or_default();
let zero = Balance::from('0');
if amount < zero || (limit == zero && amount > limit) {
log!("EXCEED_THE_LIMIT");
return "EXCEED_THE_LIMIT";
}
Promise::new(to).transfer(amount);
let balance = self.balances.get(&from).unwrap_or_default();
self.balances.insert(&from, &(balance - amount));
"END"
}
}
/// test
#[cfg(not(target_arch = "wasm32"))]
#[cfg(test)]
mod bytepay_near_test {
use near_sdk::{testing_env, VMContext};
use near_sdk::MockedBlockchain;
use super::*;
// use serde_json::to_string;
fn get_context(input: Vec<u8>, is_view: bool) -> VMContext {
VMContext {
current_account_id: String::from("合约拥有者账户"),
signer_account_id: String::from("签名账户"),
signer_account_pk: vec![0, 1, 2],
predecessor_account_id: String::from("前任账户"),
input,
block_index: 0,
block_timestamp: 0,
account_balance: 1000000,
account_locked_balance: 0,
storage_usage: 0,
attached_deposit: 0,
prepaid_gas: 10u64.pow(18),
random_seed: vec![0, 1, 2],
is_view,
output_data_receivers: vec![],
epoch_height: 0,
}
}
/// 测试充值
#[test]
fn test_recharge() {
let context = get_context(vec![], false);
testing_env!(context);
let mut contract = BytePayNearContract::default();
// --------------------------------------------------------------------------
let msg = contract.recharge(233);
println!("回执消息: {}", msg);
let balance = contract.get_balance(&AccountId::from("签名账户")).unwrap_or_default();
assert_eq!(balance, 233);
}
/// 测试设置白名单
#[test]
fn test_set_whitelist() {
let context = get_context(vec![], false);
testing_env!(context);
let mut contract = BytePayNearContract::default();
// --------------------------------------------------------------------------
let limit = 0;
let msg = contract.set_whitelist(AccountId::from("test-account.near.org"), limit);
println!("设置白名单回执消息: {}", msg);
assert_eq!(msg, "END");
let option = contract.get_whitelist(AccountId::from("签名账户"), AccountId::from("test-account.near.org"));
assert_eq!(option.unwrap_or_default(), limit)
}
/// 测试转账
#[test]
fn test_transfer() {
let context = get_context(vec![], false);
testing_env!(context);
let mut contract = BytePayNearContract::default();
// --------------------------------------------------------------------------
let msg = contract.transfer(env::current_account_id(), AccountId::from("test-account.near.org"), 233);
println!("回执: {}", msg)
}
}
}
test contract
cargo test --lib bytepay_near::bytepay_near_test::test_recharge -- --show-output
cargo test --lib bytepay_near::bytepay_near_test::test_set_whitelist -- --show-output
cargo test --lib bytepay_near::bytepay_near_test::test_transfer -- --show-output
view method
View contract owner: `get_owner`
Check balance: `get_balance`
**Parameter:**
| name | type |
|---------|-----------|
| account | AccountId |
#### View whitelist restrictions for a specified account: `get_whitelist`
**Parameter:**
| name | type | description |
|---------|-----------|--------------|
| current | AccountId | current user |
| account | AccountId | target users |
### change method
#### Recharge: `recharge`
**Parameter:**
| name | type |
|--------|---------|
| amount | Balance |
#### Set up a whitelist: `set_whitelist`
**Parameter:**
| name | type | description |
|---------|-----------|-------------------|
| account | AccountId | target users |
| amount | Balance | target user quota |
#### The contract administrator initiates a transfer transaction: `transfer`
**Parameter:**
| name | type | description |
|--------|-----------|-------------|
| from | AccountId | payer |
| to | AccountId | payee |
| amount | Balance | money |
use `near-cli` call example:
```shell
near view <contract_account> get_balance '{"account": "account.testnet"}'
Milestone 2 — Transfer module, task module, informal, withdraw module
Task management
Create a paid task by comment an issue, it will trigger the create task event through the webhook, and the webhook server will save the task and show it on our page, when the developer complete the task, will trigger transfer module to pay the developer
Transfer module
Trigger a payment by comment an issue, like /pay Bob NEAR, the NEAR will be transferred to the developer platform account
bob apply this task
/bytepay apply
/bytepay task pay
/bytepay pay
Withdraw module
Withdraw the NEAR from our platform to developer's own wallet, if the developer bind its own address, payment will be transferred to the account directly
Bytepay
Milestone 1 — User account management & repo management & mnemonic management & Transfer contract
User management, create an NEAR account for each developer We will provide login function, you can login our website using Github, and we will create a NEAR account for each user by default
Repo & webhook management We will fetch your GitHub repo list, so you can activate the repo you want to integrate with NEAR, the webhook module will listen to the pay event and trigger the transform module to pay developer NEAR
Address binding /bytepay bind near 5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE
Recharge management Withdraw the NEAR from our platform to developer's own wallet, if the developer bind its own address, payment will be transferred to the account directly
Transfer contract We will provide a contract, provide transfer limit, whitelist, and transfer function.
Milestone 2 — Transfer module, task module, informal, withdraw module
Create a paid task by comment an issue, it will trigger the create task event through the webhook, and the webhook server will save the task and show it on our page, when the developer complete the task, will trigger transfer module to pay the developer
/bytepay apply
/bytepay pay