Enable contract feature detection
Contracts updated to version 0.5.0.
This commit is contained in:
parent
0f74175b29
commit
545dd6d92b
11 changed files with 278 additions and 107 deletions
30
contracts/IERC165.json
Normal file
30
contracts/IERC165.json
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"_format": "hh-sol-artifact-1",
|
||||||
|
"contractName": "IERC165",
|
||||||
|
"sourceName": "@openzeppelin/contracts/utils/introspection/IERC165.sol",
|
||||||
|
"abi": [
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes4",
|
||||||
|
"name": "interfaceId",
|
||||||
|
"type": "bytes4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "supportsInterface",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bytecode": "0x",
|
||||||
|
"deployedBytecode": "0x",
|
||||||
|
"linkReferences": {},
|
||||||
|
"deployedLinkReferences": {}
|
||||||
|
}
|
30
contracts/IGate.json
Normal file
30
contracts/IGate.json
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"_format": "hh-sol-artifact-1",
|
||||||
|
"contractName": "IGate",
|
||||||
|
"sourceName": "contracts/interfaces/IGate.sol",
|
||||||
|
"abi": [
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "user",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "isAllowedUser",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bytecode": "0x",
|
||||||
|
"deployedBytecode": "0x",
|
||||||
|
"linkReferences": {},
|
||||||
|
"deployedLinkReferences": {}
|
||||||
|
}
|
57
contracts/IMinter.json
Normal file
57
contracts/IMinter.json
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
{
|
||||||
|
"_format": "hh-sol-artifact-1",
|
||||||
|
"contractName": "IMinter",
|
||||||
|
"sourceName": "contracts/interfaces/IMinter.sol",
|
||||||
|
"abi": [
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "collectible",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract IERC721Metadata",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "user",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "string",
|
||||||
|
"name": "tokenURI",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint8",
|
||||||
|
"name": "v",
|
||||||
|
"type": "uint8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "r",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "s",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "mint",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bytecode": "0x",
|
||||||
|
"deployedBytecode": "0x",
|
||||||
|
"linkReferences": {},
|
||||||
|
"deployedLinkReferences": {}
|
||||||
|
}
|
|
@ -71,6 +71,13 @@
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"stateMutability": "nonpayable",
|
"stateMutability": "nonpayable",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "withdrawReceivedAll",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bytecode": "0x",
|
"bytecode": "0x",
|
||||||
|
|
|
@ -1,21 +1,8 @@
|
||||||
{
|
{
|
||||||
"_format": "hh-sol-artifact-1",
|
"_format": "hh-sol-artifact-1",
|
||||||
"contractName": "IAdapter",
|
"contractName": "ISubscriptionAdapter",
|
||||||
"sourceName": "contracts/interfaces/IAdapter.sol",
|
"sourceName": "contracts/interfaces/ISubscriptionAdapter.sol",
|
||||||
"abi": [
|
"abi": [
|
||||||
{
|
|
||||||
"inputs": [],
|
|
||||||
"name": "collectible",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"internalType": "contract IERC721Metadata",
|
|
||||||
"name": "",
|
|
||||||
"type": "address"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stateMutability": "view",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
|
@ -97,25 +84,6 @@
|
||||||
"stateMutability": "view",
|
"stateMutability": "view",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"internalType": "address",
|
|
||||||
"name": "user",
|
|
||||||
"type": "address"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "isAllowedUser",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"internalType": "bool",
|
|
||||||
"name": "",
|
|
||||||
"type": "bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stateMutability": "view",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
|
@ -135,39 +103,6 @@
|
||||||
"stateMutability": "view",
|
"stateMutability": "view",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"internalType": "address",
|
|
||||||
"name": "user",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "string",
|
|
||||||
"name": "tokenURI",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "uint8",
|
|
||||||
"name": "v",
|
|
||||||
"type": "uint8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "r",
|
|
||||||
"type": "bytes32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"internalType": "bytes32",
|
|
||||||
"name": "s",
|
|
||||||
"type": "bytes32"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "mint",
|
|
||||||
"outputs": [],
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"inputs": [],
|
"inputs": [],
|
||||||
"name": "subscription",
|
"name": "subscription",
|
|
@ -782,6 +782,19 @@ components:
|
||||||
description: Blockchain contract address.
|
description: Blockchain contract address.
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
|
blockchain_features:
|
||||||
|
description: Blockchain contract features.
|
||||||
|
type: object
|
||||||
|
nullable: true
|
||||||
|
properties:
|
||||||
|
minter:
|
||||||
|
description: Minter feature flag.
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
subscription:
|
||||||
|
description: Subscription feature flag.
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
blockchain_info:
|
blockchain_info:
|
||||||
description: Additional information about blockchain
|
description: Additional information about blockchain
|
||||||
type: object
|
type: object
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use web3::{
|
use web3::{
|
||||||
api::Web3,
|
api::Web3,
|
||||||
contract::{Contract, Options},
|
contract::{Contract, Error as ContractError, Options},
|
||||||
ethabi,
|
ethabi,
|
||||||
transports::Http,
|
transports::Http,
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,10 @@ use super::sync::{
|
||||||
};
|
};
|
||||||
use super::utils::parse_address;
|
use super::utils::parse_address;
|
||||||
|
|
||||||
const ADAPTER: &str = "IAdapter";
|
const ERC165: &str = "IERC165";
|
||||||
|
const GATE: &str = "IGate";
|
||||||
|
const MINTER: &str = "IMinter";
|
||||||
|
const SUBSCRIPTION_ADAPTER: &str = "ISubscriptionAdapter";
|
||||||
const SUBSCRIPTION: &str = "ISubscription";
|
const SUBSCRIPTION: &str = "ISubscription";
|
||||||
const ERC721: &str = "IERC721Metadata";
|
const ERC721: &str = "IERC721Metadata";
|
||||||
|
|
||||||
|
@ -51,13 +54,38 @@ fn load_abi(
|
||||||
Ok(abi)
|
Ok(abi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://eips.ethereum.org/EIPS/eip-165
|
||||||
|
// Interface identifier is the XOR of all function selectors in the interface
|
||||||
|
fn interface_signature(interface: ðabi::Contract) -> [u8; 4] {
|
||||||
|
interface.functions()
|
||||||
|
.map(|func| func.short_signature())
|
||||||
|
.fold([0; 4], |mut acc, item| {
|
||||||
|
for i in 0..4 {
|
||||||
|
acc[i] ^= item[i];
|
||||||
|
};
|
||||||
|
acc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if contract supports interface (per ERC-165)
|
||||||
|
async fn is_interface_supported(
|
||||||
|
contract: &Contract<Http>,
|
||||||
|
interface: ðabi::Contract,
|
||||||
|
) -> Result<bool, ContractError> {
|
||||||
|
let signature = interface_signature(interface);
|
||||||
|
contract.query(
|
||||||
|
"supportsInterface",
|
||||||
|
(signature,), None, Options::default(), None,
|
||||||
|
).await
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ContractSet {
|
pub struct ContractSet {
|
||||||
pub web3: Web3<Http>,
|
pub web3: Web3<Http>,
|
||||||
|
|
||||||
pub adapter: Contract<Http>,
|
pub gate: Option<Contract<Http>>,
|
||||||
pub collectible: Contract<Http>,
|
pub collectible: Option<Contract<Http>>,
|
||||||
pub subscription: Contract<Http>,
|
pub subscription: Option<Contract<Http>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -75,15 +103,40 @@ pub async fn get_contracts(
|
||||||
if chain_id != config.ethereum_chain_id().into() {
|
if chain_id != config.ethereum_chain_id().into() {
|
||||||
return Err(EthereumError::ImproperlyConfigured("incorrect chain ID"));
|
return Err(EthereumError::ImproperlyConfigured("incorrect chain ID"));
|
||||||
};
|
};
|
||||||
let adapter_abi = load_abi(&config.contract_dir, ADAPTER)?;
|
|
||||||
let adapter_address = parse_address(&config.contract_address)?;
|
let adapter_address = parse_address(&config.contract_address)?;
|
||||||
let adapter = Contract::new(
|
let erc165_abi = load_abi(&config.contract_dir, ERC165)?;
|
||||||
|
let erc165 = Contract::new(
|
||||||
web3.eth(),
|
web3.eth(),
|
||||||
adapter_address,
|
adapter_address,
|
||||||
adapter_abi,
|
erc165_abi,
|
||||||
);
|
);
|
||||||
|
|
||||||
let collectible_address = adapter.query(
|
let mut maybe_gate = None;
|
||||||
|
let mut maybe_collectible = None;
|
||||||
|
let mut maybe_subscription = None;
|
||||||
|
let mut sync_targets = vec![];
|
||||||
|
|
||||||
|
let gate_abi = load_abi(&config.contract_dir, GATE)?;
|
||||||
|
if is_interface_supported(&erc165, &gate_abi).await? {
|
||||||
|
let gate = Contract::new(
|
||||||
|
web3.eth(),
|
||||||
|
adapter_address,
|
||||||
|
gate_abi,
|
||||||
|
);
|
||||||
|
maybe_gate = Some(gate);
|
||||||
|
log::info!("found gate interface");
|
||||||
|
};
|
||||||
|
|
||||||
|
let minter_abi = load_abi(&config.contract_dir, MINTER)?;
|
||||||
|
if is_interface_supported(&erc165, &minter_abi).await? {
|
||||||
|
let minter = Contract::new(
|
||||||
|
web3.eth(),
|
||||||
|
adapter_address,
|
||||||
|
minter_abi,
|
||||||
|
);
|
||||||
|
log::info!("found minter interface");
|
||||||
|
let collectible_address = minter.query(
|
||||||
"collectible",
|
"collectible",
|
||||||
(), None, Options::default(), None,
|
(), None, Options::default(), None,
|
||||||
).await?;
|
).await?;
|
||||||
|
@ -94,8 +147,19 @@ pub async fn get_contracts(
|
||||||
collectible_abi,
|
collectible_abi,
|
||||||
);
|
);
|
||||||
log::info!("collectible item contract address is {:?}", collectible.address());
|
log::info!("collectible item contract address is {:?}", collectible.address());
|
||||||
|
sync_targets.push(collectible.address());
|
||||||
|
maybe_collectible = Some(collectible);
|
||||||
|
};
|
||||||
|
|
||||||
let subscription_address = adapter.query(
|
let subscription_adapter_abi = load_abi(&config.contract_dir, SUBSCRIPTION_ADAPTER)?;
|
||||||
|
if is_interface_supported(&erc165, &subscription_adapter_abi).await? {
|
||||||
|
let subscription_adapter = Contract::new(
|
||||||
|
web3.eth(),
|
||||||
|
adapter_address,
|
||||||
|
subscription_adapter_abi,
|
||||||
|
);
|
||||||
|
log::info!("found subscription interface");
|
||||||
|
let subscription_address = subscription_adapter.query(
|
||||||
"subscription",
|
"subscription",
|
||||||
(), None, Options::default(), None,
|
(), None, Options::default(), None,
|
||||||
).await?;
|
).await?;
|
||||||
|
@ -106,20 +170,23 @@ pub async fn get_contracts(
|
||||||
subscription_abi,
|
subscription_abi,
|
||||||
);
|
);
|
||||||
log::info!("subscription contract address is {:?}", subscription.address());
|
log::info!("subscription contract address is {:?}", subscription.address());
|
||||||
|
sync_targets.push(subscription.address());
|
||||||
|
maybe_subscription = Some(subscription);
|
||||||
|
};
|
||||||
|
|
||||||
let current_block = get_current_block_number(&web3, storage_dir).await?;
|
let current_block = get_current_block_number(&web3, storage_dir).await?;
|
||||||
log::info!("current block is {}", current_block);
|
log::info!("current block is {}", current_block);
|
||||||
let sync_state = SyncState::new(
|
let sync_state = SyncState::new(
|
||||||
current_block,
|
current_block,
|
||||||
vec![collectible.address(), subscription.address()],
|
sync_targets,
|
||||||
storage_dir,
|
storage_dir,
|
||||||
);
|
);
|
||||||
|
|
||||||
let contract_set = ContractSet {
|
let contract_set = ContractSet {
|
||||||
web3,
|
web3,
|
||||||
adapter,
|
gate: maybe_gate,
|
||||||
collectible,
|
collectible: maybe_collectible,
|
||||||
subscription,
|
subscription: maybe_subscription,
|
||||||
};
|
};
|
||||||
Ok(Blockchain { contract_set, sync_state })
|
Ok(Blockchain { contract_set, sync_state })
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,12 @@ pub async fn is_allowed_user(
|
||||||
contract_set: &ContractSet,
|
contract_set: &ContractSet,
|
||||||
user_address: &str,
|
user_address: &str,
|
||||||
) -> Result<bool, EthereumError> {
|
) -> Result<bool, EthereumError> {
|
||||||
|
let gate = match &contract_set.gate {
|
||||||
|
Some(contract) => contract,
|
||||||
|
None => return Ok(true), // no gate
|
||||||
|
};
|
||||||
let user_address = parse_address(user_address)?;
|
let user_address = parse_address(user_address)?;
|
||||||
let result: bool = contract_set.adapter.query(
|
let result: bool = gate.query(
|
||||||
"isAllowedUser", (user_address,),
|
"isAllowedUser", (user_address,),
|
||||||
None, Options::default(), None,
|
None, Options::default(), None,
|
||||||
).await?;
|
).await?;
|
||||||
|
|
|
@ -3,8 +3,15 @@ use std::collections::HashMap;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
use crate::ethereum::contracts::ContractSet;
|
||||||
use crate::mastodon_api::MASTODON_API_VERSION;
|
use crate::mastodon_api::MASTODON_API_VERSION;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct BlockchainFeatures {
|
||||||
|
minter: bool,
|
||||||
|
subscription: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct InstanceInfo {
|
pub struct InstanceInfo {
|
||||||
uri: String,
|
uri: String,
|
||||||
|
@ -19,6 +26,7 @@ pub struct InstanceInfo {
|
||||||
blockchain_id: Option<String>,
|
blockchain_id: Option<String>,
|
||||||
blockchain_explorer_url: Option<String>,
|
blockchain_explorer_url: Option<String>,
|
||||||
blockchain_contract_address: Option<String>,
|
blockchain_contract_address: Option<String>,
|
||||||
|
blockchain_features: Option<BlockchainFeatures>,
|
||||||
blockchain_info: Option<HashMap<String, String>>,
|
blockchain_info: Option<HashMap<String, String>>,
|
||||||
ipfs_gateway_url: Option<String>,
|
ipfs_gateway_url: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -31,8 +39,14 @@ fn get_full_api_version(version: &str) -> String {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Config> for InstanceInfo {
|
impl InstanceInfo {
|
||||||
fn from(config: &Config) -> Self {
|
pub fn create(config: &Config, maybe_blockchain: Option<&ContractSet>) -> Self {
|
||||||
|
let blockchain_features = maybe_blockchain.map(|contract_set| {
|
||||||
|
BlockchainFeatures {
|
||||||
|
minter: contract_set.collectible.is_some(),
|
||||||
|
subscription: contract_set.subscription.is_some(),
|
||||||
|
}
|
||||||
|
});
|
||||||
Self {
|
Self {
|
||||||
uri: config.instance().host(),
|
uri: config.instance().host(),
|
||||||
title: config.instance_title.clone(),
|
title: config.instance_title.clone(),
|
||||||
|
@ -48,6 +62,7 @@ impl From<&Config> for InstanceInfo {
|
||||||
.and_then(|val| val.explorer_url.clone()),
|
.and_then(|val| val.explorer_url.clone()),
|
||||||
blockchain_contract_address: config.blockchain.as_ref()
|
blockchain_contract_address: config.blockchain.as_ref()
|
||||||
.map(|val| val.contract_address.clone()),
|
.map(|val| val.contract_address.clone()),
|
||||||
|
blockchain_features: blockchain_features,
|
||||||
blockchain_info: config.blockchain.as_ref()
|
blockchain_info: config.blockchain.as_ref()
|
||||||
.and_then(|val| val.chain_info.clone()),
|
.and_then(|val| val.chain_info.clone()),
|
||||||
ipfs_gateway_url: config.ipfs_gateway_url.clone(),
|
ipfs_gateway_url: config.ipfs_gateway_url.clone(),
|
||||||
|
|
|
@ -2,13 +2,18 @@ use actix_web::{get, web, HttpResponse, Scope};
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::errors::HttpError;
|
use crate::errors::HttpError;
|
||||||
|
use crate::ethereum::contracts::ContractSet;
|
||||||
use super::types::InstanceInfo;
|
use super::types::InstanceInfo;
|
||||||
|
|
||||||
#[get("")]
|
#[get("")]
|
||||||
async fn instance_view(
|
async fn instance_view(
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
|
maybe_blockchain: web::Data<Option<ContractSet>>,
|
||||||
) -> Result<HttpResponse, HttpError> {
|
) -> Result<HttpResponse, HttpError> {
|
||||||
let instance = InstanceInfo::from(config.as_ref());
|
let instance = InstanceInfo::create(
|
||||||
|
config.as_ref(),
|
||||||
|
maybe_blockchain.as_ref().as_ref(),
|
||||||
|
);
|
||||||
Ok(HttpResponse::Ok().json(instance))
|
Ok(HttpResponse::Ok().json(instance))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,9 +46,13 @@ async fn nft_monitor_task(
|
||||||
Some(blockchain) => blockchain,
|
Some(blockchain) => blockchain,
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
|
let collectible = match &blockchain.contract_set.collectible {
|
||||||
|
Some(contract) => contract,
|
||||||
|
None => return Ok(()), // feature not enabled
|
||||||
|
};
|
||||||
process_nft_events(
|
process_nft_events(
|
||||||
&blockchain.contract_set.web3,
|
&blockchain.contract_set.web3,
|
||||||
&blockchain.contract_set.collectible,
|
&collectible,
|
||||||
&mut blockchain.sync_state,
|
&mut blockchain.sync_state,
|
||||||
db_pool,
|
db_pool,
|
||||||
token_waitlist_map,
|
token_waitlist_map,
|
||||||
|
@ -64,9 +68,13 @@ async fn subscription_monitor_task(
|
||||||
Some(blockchain) => blockchain,
|
Some(blockchain) => blockchain,
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
|
let subscription = match &blockchain.contract_set.subscription {
|
||||||
|
Some(contract) => contract,
|
||||||
|
None => return Ok(()), // feature not enabled
|
||||||
|
};
|
||||||
check_subscriptions(
|
check_subscriptions(
|
||||||
&blockchain.contract_set.web3,
|
&blockchain.contract_set.web3,
|
||||||
&blockchain.contract_set.subscription,
|
&subscription,
|
||||||
&mut blockchain.sync_state,
|
&mut blockchain.sync_state,
|
||||||
db_pool,
|
db_pool,
|
||||||
).await.map_err(Error::from)
|
).await.map_err(Error::from)
|
||||||
|
|
Loading…
Reference in a new issue