Skip to content

Commit

Permalink
feat: P-914 implemented NFT token holder VC for MFAN on Polygon
Browse files Browse the repository at this point in the history
  • Loading branch information
higherordertech authored and higherordertech committed Jul 9, 2024
1 parent 660f468 commit d2cbdd8
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 31 deletions.
3 changes: 3 additions & 0 deletions primitives/core/src/assertion/web3_nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ pub enum Web3NftType {
WeirdoGhostGang,
#[codec(index = 1)]
Club3Sbt,
#[codec(index = 2)]
MFan,
}

impl Web3NftType {
pub fn get_supported_networks(&self) -> Vec<Web3Network> {
match self {
Self::WeirdoGhostGang => vec![Web3Network::Ethereum],
Self::Club3Sbt => vec![Web3Network::Bsc, Web3Network::Polygon, Web3Network::Arbitrum],
Self::MFan => vec![Web3Network::Polygon],
}
}
}
1 change: 1 addition & 0 deletions tee-worker/cli/lit_test_dr_vc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ assertion_vec=(
"platform-user karat-dao-user"
"nft-holder weirdo-ghost-gang"
"nft-holder club3-sbt"
"nft-holder mfan"
)

assertions=()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ pub enum PlatformUserCommand {
pub enum NftHolderCommand {
WeirdoGhostGang,
Club3Sbt,
MFan,
}

// positional args (to vec) + required arg + optional arg is a nightmare combination for clap parser,
Expand Down Expand Up @@ -640,6 +641,7 @@ impl Command {
Command::NftHolder(arg) => Ok(match arg {
NftHolderCommand::WeirdoGhostGang => NftHolder(Web3NftType::WeirdoGhostGang),
NftHolderCommand::Club3Sbt => NftHolder(Web3NftType::Club3Sbt),
NftHolderCommand::MFan => NftHolder(Web3NftType::MFan),
}),
Command::Dynamic(arg) => {
let decoded_id = hex::decode(&arg.smart_contract_id.clone()).unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ export default {
},
// Web3NftType
Web3NftType: {
_enum: ["WeirdoGhostGang", "Club3Sbt"],
_enum: ["WeirdoGhostGang", "Club3Sbt", "MFan"],
},
},
};
82 changes: 82 additions & 0 deletions tee-worker/litentry/core/assertion-build-v2/src/nft_holder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,28 @@ mod tests {
})
}

fn create_mfan_assertion_logic() -> Box<AssertionLogic> {
Box::new(AssertionLogic::Or {
items: vec![Box::new(AssertionLogic::And {
items: vec![
Box::new(AssertionLogic::Item {
src: "$network".into(),
op: Op::Equal,
dst: "polygon".into(),
}),
Box::new(AssertionLogic::Item {
src: "$address".into(),
op: Op::Equal,
dst: Web3NftType::MFan
.get_nft_address(Web3Network::Polygon)
.unwrap()
.into(),
}),
],
})],
})
}

fn init() -> DataProviderConfig {
let _ = env_logger::builder().is_test(true).try_init();
let url = run(0).unwrap();
Expand Down Expand Up @@ -307,4 +329,64 @@ mod tests {
},
}
}

#[test]
fn build_mfan_holder_works() {
let data_provider_config = init();
let mut address =
decode_hex("0x49ad262c49c7aa708cc2df262ed53b64a17dd5ee".as_bytes().to_vec())
.unwrap()
.as_slice()
.try_into()
.unwrap();
let mut identities: Vec<IdentityNetworkTuple> =
vec![(Identity::Evm(address), vec![Web3Network::Polygon])];

let mut req = crate_assertion_build_request(Web3NftType::MFan, identities);
match build(&req, Web3NftType::MFan, &data_provider_config) {
Ok(credential) => {
log::info!("build MFan holder done");
assert_eq!(
*(credential.credential_subject.assertions.first().unwrap()),
AssertionLogic::And {
items: vec![
create_token_assertion_logic(Web3NftType::MFan),
create_mfan_assertion_logic(),
]
}
);
assert_eq!(*(credential.credential_subject.values.first().unwrap()), true);
},
Err(e) => {
panic!("build MFan holder failed with error {:?}", e);
},
}

address = decode_hex("0x45cdb67696802b9d01ed156b883269dbdb9c6239".as_bytes().to_vec())
.unwrap()
.as_slice()
.try_into()
.unwrap();
identities = vec![(Identity::Evm(address), vec![Web3Network::Polygon])];

req = crate_assertion_build_request(Web3NftType::MFan, identities);
match build(&req, Web3NftType::MFan, &data_provider_config) {
Ok(credential) => {
log::info!("build MFan holder done");
assert_eq!(
*(credential.credential_subject.assertions.first().unwrap()),
AssertionLogic::And {
items: vec![
create_token_assertion_logic(Web3NftType::MFan),
create_mfan_assertion_logic(),
]
}
);
assert_eq!(*(credential.credential_subject.values.first().unwrap()), false);
},
Err(e) => {
panic!("build MFan holder failed with error {:?}", e);
},
}
}
}
4 changes: 4 additions & 0 deletions tee-worker/litentry/core/common/src/web3_nft/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ impl NftName for Web3NftType {
match self {
Self::WeirdoGhostGang => "Weirdo Ghost Gang",
Self::Club3Sbt => "Club3 SBT",
Self::MFan => "MFAN",
}
}
}
Expand All @@ -54,6 +55,9 @@ impl NftAddress for Web3NftType {
Some("0xAc2e4e67cffa5E82bfA1e169e5F9aa405114C982"),
(Self::Club3Sbt, Web3Network::Arbitrum) =>
Some("0xcccFF19FB8a4a2A206d07842b8F8c8c0A11904C2"),
// MFan
(Self::MFan, Web3Network::Polygon) =>
Some("0x9aBc7C604C27622f9CD56bd1628F6321c32bBBf6"),
_ => None,
}
}
Expand Down
105 changes: 75 additions & 30 deletions tee-worker/litentry/core/service/src/web3_nft/nft_holder/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,23 @@ pub fn has_nft_721(
None => Ok(LoopControls::Continue),
}
},
Web3Network::Polygon => {
match check_nft_via_moralis(
network,
address.1.clone(),
token_address.into(),
data_provider_config,
) {
Ok(r) => {
if r {
result = true;
return Ok(LoopControls::Break)
}
Ok(LoopControls::Continue)
},
Err(err) => Err(err),
}
},
_ => Ok(LoopControls::Continue),
}
},
Expand All @@ -85,14 +102,57 @@ pub fn has_nft_721(
Ok(result)
}

pub fn check_nft_via_moralis(
network: Web3Network,
address: String,
token_address: String,
data_provider_config: &DataProviderConfig,
) -> Result<bool, Error> {
let mut client = MoralisClient::new(data_provider_config);

match network {
Web3Network::Bsc | Web3Network::Ethereum | Web3Network::Polygon | Web3Network::Arbitrum => {
let mut cursor: Option<String> = None;
'inner: loop {
let param = GetNftsByWalletParam {
address: address.clone(),
chain: MoralisChainParam::new(&network),
token_addresses: Some(vec![token_address.clone()]),
limit: None,
cursor,
};
match client.get_nfts_by_wallet(&param, false) {
Ok(resp) => {
cursor = resp.cursor;
for item in &resp.result {
match item.amount.parse::<u32>() {
Ok(balance) =>
if balance > 0 {
return Ok(true)
},
Err(_) => return Err(ErrorDetail::ParseError),
}
}
},
Err(err) => return Err(err.into_error_detail()),
}
if cursor.is_none() {
break 'inner
}
}
Ok(false)
},
_ => Ok(false),
}
}

// support ERC1155/BEP1155 nft token
pub fn has_nft_1155(
addresses: Vec<(Web3Network, String)>,
nft_type: Web3NftType,
data_provider_config: &DataProviderConfig,
) -> Result<bool, Error> {
let mut result = false;
let mut client = MoralisClient::new(data_provider_config);

loop_with_abort_strategy(
addresses,
Expand All @@ -105,36 +165,21 @@ pub fn has_nft_1155(
| Web3Network::Ethereum
| Web3Network::Polygon
| Web3Network::Arbitrum => {
let mut cursor: Option<String> = None;
'inner: loop {
let param = GetNftsByWalletParam {
address: address.1.clone(),
chain: MoralisChainParam::new(&network),
token_addresses: Some(vec![token_address.into()]),
limit: None,
cursor,
};
match client.get_nfts_by_wallet(&param, false) {
Ok(resp) => {
cursor = resp.cursor;
for item in &resp.result {
match item.amount.parse::<u32>() {
Ok(balance) =>
if balance > 0 {
result = true;
return Ok(LoopControls::Break)
},
Err(_) => return Err(ErrorDetail::ParseError),
}
}
},
Err(err) => return Err(err.into_error_detail()),
}
if cursor.is_none() {
break 'inner
}
match check_nft_via_moralis(
network,
address.1.clone(),
token_address.into(),
data_provider_config,
) {
Ok(r) => {
if r {
result = true;
return Ok(LoopControls::Break)
}
Ok(LoopControls::Continue)
},
Err(err) => Err(err),
}
Ok(LoopControls::Continue)
},
_ => Ok(LoopControls::Continue),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ pub fn has_nft(
Web3NftType::WeirdoGhostGang =>
common::has_nft_721(addresses, nft_type, data_provider_config),
Web3NftType::Club3Sbt => common::has_nft_1155(addresses, nft_type, data_provider_config),
Web3NftType::MFan => common::has_nft_721(addresses, nft_type, data_provider_config),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ export const mockAssertions = [
NftHolder: 'Club3Sbt',
},
},
{
description: 'You are a holder of a certain kind of NFT',
assertion: {
NftHolder: 'MFan',
},
},

// TokenHoldingAmount
{
Expand Down

0 comments on commit d2cbdd8

Please sign in to comment.