defarm-sdk
Version:
DeFarm SDK - On-premise blockchain data processing and tokenization engine for agriculture supply chain
400 lines (345 loc) • 10.5 kB
text/typescript
import type { Asset } from '../types';
interface BlockchainConfig {
enabled: boolean;
network: 'stellar' | 'ethereum' | 'polygon';
endpoint?: string;
credentials?: {
publicKey?: string;
privateKey?: string;
apiKey?: string;
};
}
interface BlockchainResult {
transactionId: string;
blockNumber: number;
timestamp: Date;
}
export interface SignedTransaction {
source: string;
fee: string;
operations: any[];
sequence: string;
timeBounds?: {
minTime: number;
maxTime: number;
};
signatures: Array<{
hint: string;
signature: string;
}>;
}
// New interfaces for tokenization
export interface TokenizationBlockchainConfig {
network: 'stellar' | 'ethereum' | 'polygon';
rpcUrl: string;
contractAddresses: {
nft: string;
ipcm: string;
valuechains: string;
};
}
export interface MintNFTParams {
to: string;
valuechainId: string;
metadataUrl: string;
asset: Asset;
}
export interface MintNFTResult {
success: boolean;
tokenId?: string;
contractAddress?: string;
transactionHash?: string;
error?: string;
}
export interface NFTInfo {
tokenId: string;
contractAddress: string;
owner: string;
metadataUrl: string;
valuechainId: string;
}
/**
* Service for blockchain integration
* Enhanced with tokenization capabilities using DeFarm backbone contracts
*/
export class BlockchainService {
private config: BlockchainConfig;
private tokenizationConfig?: TokenizationBlockchainConfig;
private initialized = false;
constructor(config: BlockchainConfig, tokenizationConfig?: TokenizationBlockchainConfig) {
this.config = config;
this.tokenizationConfig = tokenizationConfig;
}
async initialize(): Promise<void> {
if (!this.config.enabled) {
return;
}
// In real implementation, would initialize blockchain connection
console.log(`Initializing blockchain service for ${this.config.network}`);
// Verify credentials
if (!this.config.credentials?.publicKey) {
throw new Error('Blockchain public key required');
}
this.initialized = true;
}
async submitAsset(asset: Asset): Promise<BlockchainResult> {
if (!this.initialized) {
throw new Error('Blockchain service not initialized');
}
// Create hash of asset data
const assetHash = this.createAssetHash(asset);
// In real implementation, would submit to blockchain
console.log(`Submitting asset ${asset.dfid} to ${this.config.network} blockchain`);
// Simulate blockchain submission
return {
transactionId: `tx_${Date.now()}_${Math.random().toString(36).substring(7)}`,
blockNumber: Math.floor(Math.random() * 1000000),
timestamp: new Date()
};
}
async verifyAsset(dfid: string, transactionId: string): Promise<boolean> {
if (!this.initialized) {
throw new Error('Blockchain service not initialized');
}
// In real implementation, would verify on blockchain
console.log(`Verifying asset ${dfid} with transaction ${transactionId}`);
// Simulate verification
return true;
}
async disconnect(): Promise<void> {
if (this.initialized) {
console.log('Disconnecting blockchain service');
this.initialized = false;
}
}
private createAssetHash(asset: Asset): string {
// In real implementation, would use proper hashing
const data = {
dfid: asset.dfid,
name: asset.name,
category: asset.category,
ownership: asset.ownership.ownerId,
created: asset.metadata.created
};
// Simple hash simulation
return Buffer.from(JSON.stringify(data)).toString('base64');
}
/**
* Mint NFT using DeFarm's smart contract (for tokenization)
*/
async mintNFT(params: MintNFTParams): Promise<MintNFTResult> {
if (!this.tokenizationConfig) {
return {
success: false,
error: 'Tokenization not configured'
};
}
try {
// Call DeFarm's tokenization API (uses backbone smart contracts)
const response = await fetch(`${this.getDeFarmAPIUrl()}/tokenization/mint`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.getDeFarmAPIKey()}`
},
body: JSON.stringify({
to: params.to,
valuechainId: params.valuechainId,
metadataUrl: params.metadataUrl,
contractId: this.tokenizationConfig.contractAddresses.nft,
rpcUrl: this.tokenizationConfig.rpcUrl,
assetData: {
dfid: params.asset.dfid,
category: params.asset.category,
subcategory: params.asset.subcategory,
name: params.asset.name
}
})
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(`Mint API failed: ${response.status} ${errorData.error || response.statusText}`);
}
const result = await response.json();
return {
success: result.success,
tokenId: result.tokenId,
contractAddress: this.tokenizationConfig.contractAddresses.nft,
transactionHash: result.transactionHash,
error: result.error
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown blockchain error'
};
}
}
/**
* Map CID to blockchain using IPCM contract
*/
async mapCIDToBlockchain(key: string, cid: string): Promise<{
success: boolean;
transactionHash?: string;
error?: string;
}> {
if (!this.tokenizationConfig) {
return {
success: false,
error: 'Tokenization not configured'
};
}
try {
// Call DeFarm's CID mapping API (uses backbone IPCM contract)
const response = await fetch(`${this.getDeFarmAPIUrl()}/tokenization/map-cid`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.getDeFarmAPIKey()}`
},
body: JSON.stringify({
key,
cid,
contractId: this.tokenizationConfig.contractAddresses.ipcm,
rpcUrl: this.tokenizationConfig.rpcUrl
})
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(`CID mapping API failed: ${response.status} ${errorData.error || response.statusText}`);
}
const result = await response.json();
return {
success: result.success,
transactionHash: result.transactionHash,
error: result.error
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown CID mapping error'
};
}
}
/**
* Query NFTs owned by an address
*/
async queryNFTByOwner(ownerAddress: string): Promise<NFTInfo[]> {
if (!this.tokenizationConfig) {
return [];
}
try {
const response = await fetch(`${this.getDeFarmAPIUrl()}/tokenization/query-nfts?owner=${ownerAddress}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.getDeFarmAPIKey()}`
}
});
if (!response.ok) {
throw new Error(`NFT query failed: ${response.status} ${response.statusText}`);
}
const result = await response.json();
return result.nfts || [];
} catch (error) {
console.warn('Failed to query NFTs:', error);
return [];
}
}
/**
* Get wallet balance
*/
async getBalance(address: string): Promise<string> {
if (!this.tokenizationConfig) {
return '0';
}
try {
const response = await fetch(`${this.getDeFarmAPIUrl()}/blockchain/balance?address=${address}&network=${this.tokenizationConfig.network}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.getDeFarmAPIKey()}`
}
});
if (!response.ok) {
throw new Error(`Balance query failed: ${response.status} ${response.statusText}`);
}
const result = await response.json();
return result.balance || '0';
} catch (error) {
console.warn('Failed to get balance:', error);
return '0';
}
}
/**
* Get DeFarm API URL from environment
*/
private getDeFarmAPIUrl(): string {
return process.env.DEFARM_API_URL || 'https://api.defarm.com';
}
/**
* Get DeFarm API key from environment
*/
private getDeFarmAPIKey(): string {
return process.env.DEFARM_API_KEY || 'defarm_sdk_default_key';
}
/**
* Submit signed transaction to blockchain
*/
async submitSignedTransaction(signedTx: SignedTransaction): Promise<{
hash: string;
success: boolean;
error?: string;
}> {
if (!this.tokenizationConfig) {
return {
hash: '',
success: false,
error: 'Tokenization not configured'
};
}
try {
const response = await fetch(`${this.getDeFarmAPIUrl()}/blockchain/submit-transaction`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.getDeFarmAPIKey()}`
},
body: JSON.stringify({
network: this.tokenizationConfig.network,
signedTransaction: signedTx
})
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(`Transaction submission failed: ${response.status} ${errorData.error || response.statusText}`);
}
const result = await response.json();
return {
hash: result.transactionHash || result.hash,
success: result.success,
error: result.error
};
} catch (error) {
return {
hash: '',
success: false,
error: error instanceof Error ? error.message : 'Unknown submission error'
};
}
}
/**
* Get blockchain explorer URL for a transaction
*/
getExplorerUrl(transactionId: string): string {
const network = this.tokenizationConfig?.network || this.config.network;
switch (network) {
case 'stellar':
return `https://stellar.expert/explorer/testnet/tx/${transactionId}`;
case 'ethereum':
return `https://etherscan.io/tx/${transactionId}`;
case 'polygon':
return `https://polygonscan.com/tx/${transactionId}`;
default:
return '';
}
}
}