Wallet Integration
WIA-FIN-007 Phase 4 ensures seamless integration with all major Web3 wallets through standardized connection protocols and transaction signing.
Universal Wallet Connector
import { WIAWalletConnector } from '@wia/wallet';
const walletConnector = new WIAWalletConnector({
supportedWallets: [
'metamask',
'walletconnect',
'coinbase',
'trust',
'ledger',
'trezor',
'safe'
],
supportedChains: [1, 137, 42161, 10, 56, 43114],
appMetadata: {
name: 'WIA DApp',
description: 'WIA-compliant decentralized application',
url: 'https://app.example.com',
icons: ['https://app.example.com/icon.png']
}
});
// Auto-detect and connect to available wallet
const wallet = await walletConnector.connect();
console.log('Connected wallet:', wallet.type);
console.log('Address:', wallet.address);
console.log('Chain ID:', wallet.chainId);
// Listen for account changes
wallet.on('accountsChanged', (accounts) => {
console.log('Account changed:', accounts[0]);
});
// Listen for chain changes
wallet.on('chainChanged', (chainId) => {
console.log('Chain changed:', chainId);
});
// Request chain switch
await wallet.switchChain(137); // Polygon
// Sign message
const signature = await wallet.signMessage('Welcome to WIA DApp');
// Sign typed data (EIP-712)
const typedSignature = await wallet.signTypedData({
domain: {
name: 'WIA Token',
version: '1',
chainId: 1,
verifyingContract: contractAddress
},
types: {
Transfer: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'amount', type: 'uint256' }
]
},
value: {
from: wallet.address,
to: recipientAddress,
amount: ethers.utils.parseEther('100')
}
});
Hardware Wallet Support
// Ledger integration
const ledger = await walletConnector.connectHardware('ledger', {
derivationPath: "m/44'/60'/0'/0/0"
});
// Confirm transaction on device
await ledger.confirmOnDevice();
// Sign with hardware wallet
const hwSignature = await ledger.signTransaction(txData);
// Trezor integration
const trezor = await walletConnector.connectHardware('trezor');
const trezorTx = await trezor.signTransaction(txData);
Oracle Integration
Chainlink Price Feeds
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract WIAOracleIntegration {
mapping(address => AggregatorV3Interface) public priceFeeds;
uint256 public constant PRICE_STALENESS_THRESHOLD = 1 hours;
event PriceFeedAdded(address indexed token, address indexed priceFeed);
event PriceUpdated(address indexed token, int256 price, uint256 timestamp);
function addPriceFeed(address token, address priceFeed) external {
require(token != address(0), "Invalid token");
require(priceFeed != address(0), "Invalid price feed");
priceFeeds[token] = AggregatorV3Interface(priceFeed);
emit PriceFeedAdded(token, priceFeed);
}
function getLatestPrice(address token) public view returns (
uint256 price,
uint256 timestamp
) {
AggregatorV3Interface priceFeed = priceFeeds[token];
require(address(priceFeed) != address(0), "Price feed not set");
(
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
) = priceFeed.latestRoundData();
require(answeredInRound >= roundId, "Stale price");
require(answer > 0, "Invalid price");
require(block.timestamp - updatedAt < PRICE_STALENESS_THRESHOLD, "Price too old");
return (uint256(answer), updatedAt);
}
function getPriceWithFallback(
address token,
address[] memory fallbackFeeds
) public view returns (uint256 price, uint256 timestamp) {
try this.getLatestPrice(token) returns (uint256 p, uint256 t) {
return (p, t);
} catch {
// Try fallback feeds
for (uint i = 0; i < fallbackFeeds.length; i++) {
try AggregatorV3Interface(fallbackFeeds[i]).latestRoundData() returns (
uint80, int256 answer, uint256, uint256 updatedAt, uint80
) {
if (answer > 0 && block.timestamp - updatedAt < PRICE_STALENESS_THRESHOLD) {
return (uint256(answer), updatedAt);
}
} catch {
continue;
}
}
revert("No valid price available");
}
}
}
Decentralized Oracle Networks
// WIA Multi-Oracle Aggregator
contract WIAMultiOracleAggregator {
struct OracleData {
address oracleAddress;
uint256 weight;
bool active;
}
mapping(address => OracleData[]) public tokenOracles;
function aggregatePrice(address token) public view returns (uint256) {
OracleData[] memory oracles = tokenOracles[token];
require(oracles.length > 0, "No oracles configured");
uint256 weightedSum = 0;
uint256 totalWeight = 0;
uint256 validOracles = 0;
for (uint i = 0; i < oracles.length; i++) {
if (!oracles[i].active) continue;
try IOracle(oracles[i].oracleAddress).getPrice(token) returns (
uint256 price,
uint256 timestamp
) {
if (block.timestamp - timestamp < 1 hours && price > 0) {
weightedSum += price * oracles[i].weight;
totalWeight += oracles[i].weight;
validOracles++;
}
} catch {
continue;
}
}
require(validOracles >= 3, "Insufficient valid oracles");
return weightedSum / totalWeight;
}
}
DeFi Protocol Integration
Uniswap V3 Integration
// WIA-Uniswap Integration
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
contract WIAUniswapIntegration {
ISwapRouter public immutable swapRouter;
constructor(address _swapRouter) {
swapRouter = ISwapRouter(_swapRouter);
}
function swapExactInputSingle(
address tokenIn,
address tokenOut,
uint24 poolFee,
uint256 amountIn,
uint256 amountOutMinimum
) external returns (uint256 amountOut) {
// Approve router to spend tokens
IERC20(tokenIn).approve(address(swapRouter), amountIn);
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
fee: poolFee,
recipient: msg.sender,
deadline: block.timestamp + 300, // 5 minutes
amountIn: amountIn,
amountOutMinimum: amountOutMinimum,
sqrtPriceLimitX96: 0
});
amountOut = swapRouter.exactInputSingle(params);
}
function addLiquidity(
address token0,
address token1,
uint24 fee,
uint256 amount0,
uint256 amount1,
int24 tickLower,
int24 tickUpper
) external returns (
uint256 tokenId,
uint128 liquidity,
uint256 amount0Used,
uint256 amount1Used
) {
// Implementation for adding liquidity to V3 pool
}
}
Aave Lending Integration
// WIA-Aave Integration
import "@aave/core-v3/contracts/interfaces/IPool.sol";
contract WIAAaveIntegration {
IPool public immutable aavePool;
constructor(address _aavePool) {
aavePool = IPool(_aavePool);
}
function supply(
address asset,
uint256 amount,
address onBehalfOf
) external {
IERC20(asset).approve(address(aavePool), amount);
aavePool.supply(asset, amount, onBehalfOf, 0);
}
function withdraw(
address asset,
uint256 amount,
address to
) external returns (uint256) {
return aavePool.withdraw(asset, amount, to);
}
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf
) external {
aavePool.borrow(asset, amount, interestRateMode, 0, onBehalfOf);
}
function repay(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf
) external returns (uint256) {
IERC20(asset).approve(address(aavePool), amount);
return aavePool.repay(asset, amount, interestRateMode, onBehalfOf);
}
}
Cross-Chain Bridges
LayerZero Integration
// WIA Cross-Chain Token using LayerZero
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@layerzerolabs/solidity-examples/contracts/token/oft/v2/OFTV2.sol";
contract WIACrossChainToken is OFTV2 {
constructor(
string memory _name,
string memory _symbol,
uint8 _sharedDecimals,
address _lzEndpoint
) OFTV2(_name, _symbol, _sharedDecimals, _lzEndpoint) {}
function sendFrom(
address _from,
uint16 _dstChainId,
bytes32 _toAddress,
uint _amount,
LzCallParams calldata _callParams
) public payable override {
_send(_from, _dstChainId, _toAddress, _amount, _callParams.refundAddress, _callParams.zroPaymentAddress, _callParams.adapterParams);
}
// Estimate cross-chain transfer fee
function estimateSendFee(
uint16 _dstChainId,
bytes32 _toAddress,
uint _amount,
bool _useZro,
bytes calldata _adapterParams
) public view override returns (uint nativeFee, uint zroFee) {
return lzEndpoint.estimateFees(_dstChainId, address(this), abi.encode(_toAddress, _amount), _useZro, _adapterParams);
}
}
Wormhole Integration
// WIA-Wormhole Bridge Integration
import "@wormhole-foundation/contracts/interfaces/IWormhole.sol";
contract WIAWormholeBridge {
IWormhole public immutable wormhole;
mapping(uint16 => bytes32) public trustedRemotes;
mapping(bytes32 => bool) public processedMessages;
event TokensBridged(
address indexed sender,
uint16 targetChain,
bytes32 recipient,
uint256 amount
);
event TokensReceived(
bytes32 indexed sender,
address recipient,
uint256 amount
);
constructor(address _wormhole) {
wormhole = IWormhole(_wormhole);
}
function bridgeTokens(
uint16 targetChain,
bytes32 recipient,
uint256 amount
) external payable {
require(trustedRemotes[targetChain] != bytes32(0), "Chain not supported");
// Lock tokens
_burn(msg.sender, amount);
// Create payload
bytes memory payload = abi.encode(recipient, amount);
// Send via Wormhole
uint64 sequence = wormhole.publishMessage{value: msg.value}(
0, // nonce
payload,
1 // consistency level
);
emit TokensBridged(msg.sender, targetChain, recipient, amount);
}
function receiveTokens(bytes memory encodedVm) external {
(IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm);
require(valid, reason);
bytes32 messageHash = keccak256(encodedVm);
require(!processedMessages[messageHash], "Already processed");
require(trustedRemotes[vm.emitterChainId] == vm.emitterAddress, "Invalid emitter");
(bytes32 recipient, uint256 amount) = abi.decode(vm.payload, (bytes32, uint256));
processedMessages[messageHash] = true;
// Mint tokens to recipient
address recipientAddress = address(uint160(uint256(recipient)));
_mint(recipientAddress, amount);
emit TokensReceived(vm.emitterAddress, recipientAddress, amount);
}
}
Subgraph Integration
The Graph Protocol
// WIA Subgraph Schema (schema.graphql)
type WIAToken @entity {
id: ID!
name: String!
symbol: String!
decimals: Int!
totalSupply: BigInt!
holders: [Holder!]! @derivedFrom(field: "token")
transfers: [Transfer!]! @derivedFrom(field: "token")
}
type Holder @entity {
id: ID!
token: WIAToken!
address: Bytes!
balance: BigInt!
lastUpdated: BigInt!
}
type Transfer @entity {
id: ID!
token: WIAToken!
from: Bytes!
to: Bytes!
value: BigInt!
timestamp: BigInt!
blockNumber: BigInt!
transactionHash: Bytes!
}
// Query subgraph data
import { gql, request } from 'graphql-request';
const endpoint = 'https://api.thegraph.com/subgraphs/name/wia/smart-contract';
const query = gql\`
query GetTokenData($tokenId: ID!) {
wiaToken(id: $tokenId) {
name
symbol
totalSupply
holders(first: 100, orderBy: balance, orderDirection: desc) {
address
balance
}
transfers(first: 10, orderBy: timestamp, orderDirection: desc) {
from
to
value
timestamp
}
}
}
\`;
const data = await request(endpoint, query, { tokenId: contractAddress.toLowerCase() });
console.log('Token data:', data.wiaToken);
ENS Integration
Ethereum Name Service
import { WIAENSResolver } from '@wia/ens';
const ensResolver = new WIAENSResolver({
provider: ethersProvider,
chainId: 1
});
// Resolve ENS name to address
const address = await ensResolver.resolve('vitalik.eth');
console.log('Address:', address);
// Reverse resolve address to ENS name
const name = await ensResolver.reverseResolve(address);
console.log('ENS name:', name);
// Get ENS avatar
const avatar = await ensResolver.getAvatar('vitalik.eth');
console.log('Avatar URL:', avatar);
// Use ENS in contract interactions
const contract = new WIASmartContract({
address: await ensResolver.resolve('wia-token.eth'),
abi: contractABI,
provider: ethersProvider
});
// Send to ENS name
await contract.transfer(await ensResolver.resolve('recipient.eth'), amount);
IPFS Integration
Decentralized Storage
import { WIAIPFSClient } from '@wia/ipfs';
const ipfs = new WIAIPFSClient({
gateway: 'https://ipfs.io',
pinningService: 'https://api.pinata.cloud'
});
// Upload contract metadata to IPFS
const metadata = {
name: 'WIA Secure Token',
description: 'A secure ERC-20 token',
image: 'https://example.com/logo.png',
properties: {
totalSupply: '1000000',
decimals: 18
}
};
const cid = await ipfs.upload(metadata);
console.log('IPFS CID:', cid);
console.log('Gateway URL:', \`https://ipfs.io/ipfs/\${cid}\`);
// Retrieve from IPFS
const retrievedMetadata = await ipfs.get(cid);
console.log('Retrieved:', retrievedMetadata);
Analytics and Monitoring
Dune Analytics Integration
// Query Dune Analytics for contract metrics
import { WIADuneClient } from '@wia/analytics';
const dune = new WIADuneClient({
apiKey: process.env.DUNE_API_KEY
});
const metrics = await dune.query({
queryId: 1234567,
parameters: {
contract_address: contractAddress
}
});
console.log('Total transfers:', metrics.total_transfers);
console.log('Unique holders:', metrics.unique_holders);
console.log('24h volume:', metrics.volume_24h);
Phase 4 Integration completes the WIA-FIN-007 standard by enabling seamless connectivity with the entire blockchain ecosystem. Next, we'll explore implementation and certification in Chapter 8.