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

(WIP) MFT batch transfers #1

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
3 changes: 0 additions & 3 deletions examples/approval-receiver/.cargo/config

This file was deleted.

2 changes: 0 additions & 2 deletions examples/approval-receiver/.gitignore

This file was deleted.

20 changes: 0 additions & 20 deletions examples/approval-receiver/Cargo.toml

This file was deleted.

Binary file removed examples/approval-receiver/out/nep_246_ccc.wasm
Binary file not shown.
14 changes: 0 additions & 14 deletions examples/approval-receiver/scripts/build.sh

This file was deleted.

5 changes: 2 additions & 3 deletions examples/multi-token/.cargo/config
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
[build]
rustflags = ["-C", "link-args=-s"]
target = "wasm32-unknown-unknown"
[target.wasm32-unknown-unknown]
rustflags = ["-C", "link-arg=-s"]
2 changes: 0 additions & 2 deletions examples/multi-token/.gitignore

This file was deleted.

31 changes: 22 additions & 9 deletions examples/multi-token/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
[package]
name = "nep-246-test"
name = "multi-token-wrapper"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib"]

[dependencies]
nep-246 = { path = "../../" }
[dev-dependencies]
anyhow = "1.0"
near-primitives = "0.5.0"
near-sdk = "4.0.0-pre.6"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bump this latest

near-units = "0.2.0"
serde_json = "1.0"
tokio = { version = "1.14", features = ["full"] }
workspaces = "0.1.1"

# remember to include a line for each contract
multi-token = { path = "./mt" }
defi = { path = "./test-contract-defi" }
approval-receiver = { path = "./test-approval-receiver" }

[profile.release]
codegen-units = 1
Expand All @@ -19,4 +24,12 @@ opt-level = "z"
lto = true
debug = false
panic = "abort"
overflow-checks = true
overflow-checks = true

[workspace]
# remember to include a member for each contract
members = [
"mt",
"test-contract-defi",
"test-approval-receiver",
]
9 changes: 9 additions & 0 deletions examples/multi-token/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash
TARGET="${CARGO_TARGET_DIR:-target}"
set -e
cd "`dirname $0`"

cargo build --all --target wasm32-unknown-unknown --release
cp $TARGET/wasm32-unknown-unknown/release/defi.wasm ./res/
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cp $TARGET/wasm32-unknown-unknown/release/*.wasm ./res?

cp $TARGET/wasm32-unknown-unknown/release/multi_token.wasm ./res/
cp $TARGET/wasm32-unknown-unknown/release/approval_receiver.wasm ./res/
12 changes: 12 additions & 0 deletions examples/multi-token/mt/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "multi-token"
version = "1.1.0"
authors = ["Near Inc <[email protected]>"]
edition = "2021"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
near-sdk = "4.0.0-pre.6"
nep-246 = { path = "../../../" }
199 changes: 199 additions & 0 deletions examples/multi-token/mt/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::collections::{LazyOption};
use near_sdk::json_types::U128;
use near_sdk::Promise;
use near_sdk::{
env, near_bindgen, require, AccountId, Balance, BorshStorageKey, PanicOnDefault, PromiseOrValue,
};
use nep_246::multi_token::metadata::MT_METADATA_SPEC;
use nep_246::multi_token::token::{Approval, Token, TokenId};
use nep_246::multi_token::{
core::MultiToken,
metadata::{MtContractMetadata, TokenMetadata},
};

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]
pub struct ExampleMTContract {
tokens: MultiToken,
metadata: LazyOption<MtContractMetadata>,
}

#[derive(BorshSerialize, BorshStorageKey)]
enum StorageKey {
MultiToken,
Metadata,
TokenMetadata,
Enumeration,
Approval,
}

#[near_bindgen]
impl ExampleMTContract {
#[init]
pub fn new_default_meta(owner_id: AccountId) -> Self {
let metadata = MtContractMetadata {
spec: MT_METADATA_SPEC.to_string(),
name: "Test".to_string(),
symbol: "OMG".to_string(),
icon: None,
base_uri: None,
reference: None,
reference_hash: None,
};

Self::new(owner_id, metadata)
}

#[init]
pub fn new(owner_id: AccountId, metadata: MtContractMetadata) -> Self {
require!(!env::state_exists(), "Already initialized");
metadata.assert_valid();

Self {
tokens: MultiToken::new(
StorageKey::MultiToken,
owner_id,
Some(StorageKey::TokenMetadata),
Some(StorageKey::Enumeration),
Some(StorageKey::Approval),
),
metadata: LazyOption::new(StorageKey::Metadata, Some(&metadata)),
}
}

#[payable]
pub fn mt_mint(
&mut self,
token_owner_id: AccountId,
token_metadata: TokenMetadata,
amount: Balance,
) -> Token {
// Only the owner of the MFT contract can perform this operation
assert_eq!(env::predecessor_account_id(), self.tokens.owner_id, "Unauthorized: {} != {}", env::predecessor_account_id(), self.tokens.owner_id);
self.tokens.internal_mint(token_owner_id, Some(amount), Some(token_metadata), None)
}

pub fn register(&mut self, token_id: TokenId, account_id: AccountId) {
self.tokens.internal_register_account(&token_id, &account_id)
}
}

nep_246::impl_multi_token_core!(ExampleMTContract, tokens);
nep_246::impl_multi_token_approval!(ExampleMTContract, tokens);
nep_246::impl_multi_token_enumeration!(ExampleMTContract, tokens);

#[cfg(all(test, not(target_arch = "wasm32")))]
mod tests {
use near_sdk::test_utils::{accounts, VMContextBuilder};
use near_sdk::{testing_env};
use super::*;

fn create_token_md(title: String, description: String) -> TokenMetadata {
TokenMetadata {
title: Some(title),
description: Some(description),
media: None,
media_hash: None,
issued_at: Some(String::from("123456")),
expires_at: None,
starts_at: None,
updated_at: None,
extra: None,
reference: None,
reference_hash: None,
}
}

#[test]
fn test_transfer() {
let mut context = VMContextBuilder::new();
testing_env!(context
.signer_account_id(accounts(0))
.predecessor_account_id(accounts(0))
.build());

let mut contract = ExampleMTContract::new_default_meta(accounts(0));
let token_md = create_token_md("ABC".into(), "Alphabet token".into());

let token = contract.mt_mint(accounts(0), token_md.clone(), 1000);
assert_eq!(contract.mt_balance_of(accounts(0), token.token_id.clone()), 1000.into(), "Wrong balance");

contract.register(token.token_id.clone(), accounts(1));
assert_eq!(contract.mt_balance_of(accounts(1), token.token_id.clone()), 0.into(), "Wrong balance");

testing_env!(context.attached_deposit(1).build());
contract.mt_transfer(accounts(1), token.token_id.clone(), 4.into(), None, None);

assert_eq!(contract.mt_balance_of(accounts(0), token.token_id.clone()).0, 996, "Wrong balance");
assert_eq!(contract.mt_balance_of(accounts(1), token.token_id.clone()).0, 4, "Wrong balance");
}

#[test]
fn test_batch_transfer() {
let mut context = VMContextBuilder::new();
testing_env!(context
.signer_account_id(accounts(0))
.predecessor_account_id(accounts(0))
.build());
let mut contract = ExampleMTContract::new_default_meta(accounts(0));

let quote_token_md = create_token_md("PYC".into(), "Python token".into());
let base_token_md = create_token_md("ABC".into(), "Alphabet token".into());

let quote_token = contract.mt_mint(accounts(0), quote_token_md.clone(), 1000);
let base_token = contract.mt_mint(accounts(0), base_token_md.clone(), 2000);
contract.register(quote_token.token_id.clone(), accounts(1));
contract.register(base_token.token_id.clone(), accounts(1));

testing_env!(context.attached_deposit(1).build());

// Perform the transfers
contract.mt_batch_transfer(
accounts(1),
vec![quote_token.token_id.clone(), base_token.token_id.clone()],
vec![4.into(), 600.into()],
None,
None
);

assert_eq!(contract.mt_balance_of(accounts(0), quote_token.token_id.clone()).0, 996, "Wrong balance");
assert_eq!(contract.mt_balance_of(accounts(1), quote_token.token_id.clone()).0, 4, "Wrong balance");

assert_eq!(contract.mt_balance_of(accounts(0), base_token.token_id.clone()).0, 1400, "Wrong balance");
assert_eq!(contract.mt_balance_of(accounts(1), base_token.token_id.clone()).0, 600, "Wrong balance");
}

#[test]
fn test_transfer_call() {
// How to test a multi-contract call?
let mut context = VMContextBuilder::new();
testing_env!(context
.signer_account_id(accounts(0))
.predecessor_account_id(accounts(0))
.attached_deposit(1)
.build());
let mut contract = ExampleMTContract::new_default_meta(accounts(0));
let quote_token_md = create_token_md("ABC".into(), "Alphabet token".into());

// alice starts with 1000, bob with 0.
let quote_token = contract.mt_mint(accounts(0), quote_token_md.clone(), 1000);
contract.register(quote_token.token_id.clone(), accounts(1));

let _result = contract.mt_transfer_call(
accounts(1), // receiver account
quote_token.token_id.clone(),
100, // amount
None,
String::from("invest"),
);


// println!("result: {}", result);
}

#[test]
fn test_batch_transfer_call() {

}
}
Binary file removed examples/multi-token/out/nep_246_test.wasm
Binary file not shown.
Binary file added examples/multi-token/res/approval_receiver.wasm
Binary file not shown.
Binary file added examples/multi-token/res/defi.wasm
Binary file not shown.
Binary file added examples/multi-token/res/multi_token.wasm
Binary file not shown.
14 changes: 0 additions & 14 deletions examples/multi-token/scripts/build.sh

This file was deleted.

Loading