@neuraiproject/neurai-assets 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +522 -0
- package/examples/01-create-root-asset.js +71 -0
- package/examples/02-create-sub-asset.js +79 -0
- package/examples/03-create-nfts.js +140 -0
- package/examples/04-reissue-asset.js +164 -0
- package/examples/05-create-qualifier-and-tag.js +209 -0
- package/examples/06-create-restricted-asset.js +223 -0
- package/examples/07-freeze-and-unfreeze.js +292 -0
- package/examples/08-query-assets.js +332 -0
- package/examples/09-wallet-integration.js +320 -0
- package/examples/README.md +319 -0
- package/package.json +43 -0
- package/src/NeuraiAssets.js +468 -0
- package/src/builders/BaseAssetTransactionBuilder.js +303 -0
- package/src/builders/FreezeAddressBuilder.js +271 -0
- package/src/builders/IssueQualifierBuilder.js +251 -0
- package/src/builders/IssueRestrictedBuilder.js +187 -0
- package/src/builders/IssueRootBuilder.js +173 -0
- package/src/builders/IssueSubBuilder.js +237 -0
- package/src/builders/IssueUniqueBuilder.js +255 -0
- package/src/builders/ReissueBuilder.js +246 -0
- package/src/builders/ReissueRestrictedBuilder.js +264 -0
- package/src/builders/TagAddressBuilder.js +243 -0
- package/src/builders/index.js +38 -0
- package/src/constants/assetTypes.js +23 -0
- package/src/constants/burnAddresses.js +65 -0
- package/src/constants/fees.js +61 -0
- package/src/constants/index.js +44 -0
- package/src/constants/networks.js +112 -0
- package/src/errors/AssetErrors.js +135 -0
- package/src/errors/ValidationErrors.js +87 -0
- package/src/errors/index.js +56 -0
- package/src/index.js +68 -0
- package/src/managers/BurnManager.js +222 -0
- package/src/managers/OutputOrderer.js +289 -0
- package/src/managers/OwnerTokenManager.js +265 -0
- package/src/managers/UTXOSelector.js +309 -0
- package/src/managers/index.js +16 -0
- package/src/queries/AssetQueries.js +447 -0
- package/src/queries/index.js +10 -0
- package/src/utils/amountConverter.js +115 -0
- package/src/utils/assetNameParser.js +203 -0
- package/src/utils/index.js +16 -0
- package/src/utils/networkDetector.js +144 -0
- package/src/utils/outputFormatter.js +292 -0
- package/src/validators/amountValidator.js +149 -0
- package/src/validators/assetNameValidator.js +296 -0
- package/src/validators/index.js +16 -0
- package/src/validators/ipfsValidator.js +101 -0
- package/src/validators/verifierValidator.js +146 -0
- package/tests/README.md +126 -0
- package/tests/integration/assetLifecycle.test.js +244 -0
- package/tests/mocks/rpcMock.js +156 -0
- package/tests/unit/NeuraiAssets.test.js +217 -0
- package/tests/unit/utils/amountConverter.test.js +171 -0
- package/tests/unit/utils/assetNameParser.test.js +203 -0
- package/tests/unit/validators/amountValidator.test.js +143 -0
- package/tests/unit/validators/assetNameValidator.test.js +228 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Create RESTRICTED Assets (Security Tokens)
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to create RESTRICTED assets.
|
|
5
|
+
* RESTRICTED assets are security tokens with built-in compliance controls.
|
|
6
|
+
*
|
|
7
|
+
* Format: $NAME (e.g., $SECURITY, $STOCK)
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Only addresses meeting verifier requirements can receive/hold
|
|
11
|
+
* - Can freeze individual addresses or entire asset
|
|
12
|
+
* - Uses QUALIFIER tags for compliance (e.g., #KYC_VERIFIED)
|
|
13
|
+
*
|
|
14
|
+
* Cost: 3000 XNA (most expensive asset type)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const NeuraiAssets = require('@neuraiproject/neurai-assets');
|
|
18
|
+
|
|
19
|
+
async function createRestrictedAsset() {
|
|
20
|
+
// Mock RPC function (replace with your actual RPC client)
|
|
21
|
+
const rpc = async (method, params) => {
|
|
22
|
+
console.log(`RPC Call: ${method}`, params);
|
|
23
|
+
// Your RPC implementation here
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Initialize NeuraiAssets
|
|
27
|
+
const assets = new NeuraiAssets(rpc, {
|
|
28
|
+
network: 'xna',
|
|
29
|
+
addresses: ['NYourAddress1...'],
|
|
30
|
+
changeAddress: 'NChangeAddress...',
|
|
31
|
+
toAddress: 'NReceivingAddress...'
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// Step 1: Ensure qualifiers exist
|
|
36
|
+
console.log('=== Step 1: Verify Qualifiers Exist ===\n');
|
|
37
|
+
|
|
38
|
+
// You need to create qualifiers first (see example 05)
|
|
39
|
+
const requiredQualifiers = ['#KYC_VERIFIED', '#ACCREDITED'];
|
|
40
|
+
|
|
41
|
+
for (const qualifier of requiredQualifiers) {
|
|
42
|
+
const exists = await assets.assetExists(qualifier);
|
|
43
|
+
if (!exists) {
|
|
44
|
+
console.warn(`⚠ Qualifier ${qualifier} does not exist. Create it first!`);
|
|
45
|
+
// You would need to create it using createQualifier()
|
|
46
|
+
} else {
|
|
47
|
+
console.log(`✓ Qualifier ${qualifier} exists`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Step 2: Create the RESTRICTED asset with verifier string
|
|
52
|
+
console.log('\n=== Step 2: Create RESTRICTED Asset ===\n');
|
|
53
|
+
|
|
54
|
+
const result = await assets.createRestrictedAsset({
|
|
55
|
+
assetName: '$SECURITY', // Must start with $
|
|
56
|
+
quantity: 1000000, // Total supply
|
|
57
|
+
units: 2, // Decimals (0-8)
|
|
58
|
+
verifierString: '#KYC_VERIFIED & #ACCREDITED', // Boolean logic
|
|
59
|
+
reissuable: true, // Allow reissuance
|
|
60
|
+
hasIpfs: true,
|
|
61
|
+
ipfsHash: 'QmSecurityTokenMetadata...'
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
console.log('RESTRICTED Asset created successfully!');
|
|
65
|
+
console.log('Asset Name:', '$SECURITY');
|
|
66
|
+
console.log('Owner Token:', '$SECURITY!');
|
|
67
|
+
console.log('Verifier String:', result.metadata.verifierString);
|
|
68
|
+
console.log('Required Qualifiers:', result.metadata.requiredQualifiers);
|
|
69
|
+
console.log('Burn:', result.burn, 'XNA');
|
|
70
|
+
|
|
71
|
+
console.log('\n=== Verifier String Explained ===');
|
|
72
|
+
console.log('Verifier: #KYC_VERIFIED & #ACCREDITED');
|
|
73
|
+
console.log('Meaning: Address must have BOTH tags to receive this asset');
|
|
74
|
+
console.log('- #KYC_VERIFIED (required)');
|
|
75
|
+
console.log('- #ACCREDITED (required)');
|
|
76
|
+
|
|
77
|
+
console.log('\nNext steps:');
|
|
78
|
+
console.log('1. Tag addresses with required qualifiers');
|
|
79
|
+
console.log('2. Only tagged addresses can receive $SECURITY');
|
|
80
|
+
console.log('3. Use owner token ($SECURITY!) to manage the asset');
|
|
81
|
+
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('Error creating RESTRICTED asset:', error.message);
|
|
84
|
+
|
|
85
|
+
if (error.name === 'InvalidVerifierStringError') {
|
|
86
|
+
console.error('Invalid verifier string syntax');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Example: Create RESTRICTED asset with complex verifier logic
|
|
92
|
+
async function createRestrictedWithComplexVerifier() {
|
|
93
|
+
const rpc = async (method, params) => {
|
|
94
|
+
console.log(`RPC Call: ${method}`, params);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const assets = new NeuraiAssets(rpc, {
|
|
98
|
+
network: 'xna',
|
|
99
|
+
addresses: ['NYourAddress1...'],
|
|
100
|
+
changeAddress: 'NChangeAddress...',
|
|
101
|
+
toAddress: 'NReceivingAddress...'
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
// Create RESTRICTED asset with OR logic
|
|
106
|
+
const result = await assets.createRestrictedAsset({
|
|
107
|
+
assetName: '$FLEXIBLE_TOKEN',
|
|
108
|
+
quantity: 500000,
|
|
109
|
+
units: 0,
|
|
110
|
+
// Complex verifier: (KYC AND Accredited) OR Institutional
|
|
111
|
+
verifierString: '(#KYC_VERIFIED & #ACCREDITED) | #INSTITUTIONAL',
|
|
112
|
+
reissuable: true,
|
|
113
|
+
hasIpfs: false,
|
|
114
|
+
ipfsHash: ''
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
console.log('RESTRICTED Asset with complex verifier created!');
|
|
118
|
+
console.log('Asset:', '$FLEXIBLE_TOKEN');
|
|
119
|
+
console.log('Verifier:', result.metadata.verifierString);
|
|
120
|
+
|
|
121
|
+
console.log('\n=== Verifier Logic ===');
|
|
122
|
+
console.log('Option 1: Address has #KYC_VERIFIED AND #ACCREDITED');
|
|
123
|
+
console.log('Option 2: Address has #INSTITUTIONAL');
|
|
124
|
+
console.log('Result: Address can receive if either option is true');
|
|
125
|
+
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Error:', error.message);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Example: Validate verifier string before creating asset
|
|
132
|
+
async function validateVerifierString() {
|
|
133
|
+
const rpc = async (method, params) => {
|
|
134
|
+
console.log(`RPC Call: ${method}`, params);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const assets = new NeuraiAssets(rpc, {
|
|
138
|
+
network: 'xna',
|
|
139
|
+
addresses: ['NYourAddress1...'],
|
|
140
|
+
changeAddress: 'NChangeAddress...',
|
|
141
|
+
toAddress: 'NReceivingAddress...'
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
// Test different verifier strings
|
|
146
|
+
const verifiers = [
|
|
147
|
+
'#KYC_VERIFIED', // Simple
|
|
148
|
+
'#KYC_VERIFIED & #ACCREDITED', // AND
|
|
149
|
+
'#KYC_VERIFIED | #INSTITUTIONAL', // OR
|
|
150
|
+
'(#KYC_VERIFIED & #ACCREDITED) | #INSTITUTIONAL', // Complex
|
|
151
|
+
'#KYC & (#ACCREDITED | #INSTITUTIONAL)', // Nested
|
|
152
|
+
'INVALID STRING', // Invalid
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
console.log('=== Verifier String Validation ===\n');
|
|
156
|
+
|
|
157
|
+
for (const verifier of verifiers) {
|
|
158
|
+
const isValid = await assets.isValidVerifierString(verifier);
|
|
159
|
+
console.log(`${isValid ? '✓' : '✗'} "${verifier}"`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error('Error:', error.message);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Example: Check if address can receive restricted asset
|
|
168
|
+
async function checkAddressCompliance() {
|
|
169
|
+
const rpc = async (method, params) => {
|
|
170
|
+
console.log(`RPC Call: ${method}`, params);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const assets = new NeuraiAssets(rpc, {
|
|
174
|
+
network: 'xna',
|
|
175
|
+
addresses: ['NYourAddress1...'],
|
|
176
|
+
changeAddress: 'NChangeAddress...',
|
|
177
|
+
toAddress: 'NReceivingAddress...'
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
const testAddress = 'NTestAddress...';
|
|
182
|
+
const restrictedAsset = '$SECURITY';
|
|
183
|
+
|
|
184
|
+
console.log('=== Compliance Check ===\n');
|
|
185
|
+
console.log(`Address: ${testAddress}`);
|
|
186
|
+
console.log(`Asset: ${restrictedAsset}`);
|
|
187
|
+
|
|
188
|
+
// Check if address meets verifier requirements
|
|
189
|
+
const canReceive = await assets.checkAddressRestriction(
|
|
190
|
+
testAddress,
|
|
191
|
+
restrictedAsset
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
console.log(`\nCan receive asset: ${canReceive ? 'YES ✓' : 'NO ✗'}`);
|
|
195
|
+
|
|
196
|
+
if (!canReceive) {
|
|
197
|
+
// Check what tags the address has
|
|
198
|
+
const tags = await assets.listTagsForAddress(testAddress);
|
|
199
|
+
console.log('\nCurrent tags:', tags.length > 0 ? tags : 'None');
|
|
200
|
+
|
|
201
|
+
// Get verifier requirements
|
|
202
|
+
const verifier = await assets.getVerifierString(restrictedAsset);
|
|
203
|
+
console.log('Required verifier:', verifier);
|
|
204
|
+
console.log('\nThe address needs to be tagged with required qualifiers');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
} catch (error) {
|
|
208
|
+
console.error('Error:', error.message);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Run the examples
|
|
213
|
+
console.log('=== Example 1: Create Simple RESTRICTED Asset ===\n');
|
|
214
|
+
createRestrictedAsset();
|
|
215
|
+
|
|
216
|
+
console.log('\n\n=== Example 2: Create with Complex Verifier ===\n');
|
|
217
|
+
createRestrictedWithComplexVerifier();
|
|
218
|
+
|
|
219
|
+
console.log('\n\n=== Example 3: Validate Verifier Strings ===\n');
|
|
220
|
+
validateVerifierString();
|
|
221
|
+
|
|
222
|
+
console.log('\n\n=== Example 4: Check Address Compliance ===\n');
|
|
223
|
+
checkAddressCompliance();
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Freeze and Unfreeze Operations
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to freeze/unfreeze addresses and assets.
|
|
5
|
+
* Freezing is only available for RESTRICTED assets.
|
|
6
|
+
*
|
|
7
|
+
* Requirements:
|
|
8
|
+
* - Must own the restricted asset's owner token ($ASSET!)
|
|
9
|
+
*
|
|
10
|
+
* Operations:
|
|
11
|
+
* - Freeze specific addresses (prevent trading)
|
|
12
|
+
* - Unfreeze specific addresses (allow trading again)
|
|
13
|
+
* - Global freeze (freeze entire asset)
|
|
14
|
+
* - Global unfreeze (unfreeze entire asset)
|
|
15
|
+
*
|
|
16
|
+
* Cost: No burn (only network fee)
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const NeuraiAssets = require('@neuraiproject/neurai-assets');
|
|
20
|
+
|
|
21
|
+
async function freezeAddresses() {
|
|
22
|
+
// Mock RPC function (replace with your actual RPC client)
|
|
23
|
+
const rpc = async (method, params) => {
|
|
24
|
+
console.log(`RPC Call: ${method}`, params);
|
|
25
|
+
// Your RPC implementation here
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Initialize NeuraiAssets
|
|
29
|
+
const assets = new NeuraiAssets(rpc, {
|
|
30
|
+
network: 'xna',
|
|
31
|
+
addresses: ['NYourAddress1...'],
|
|
32
|
+
changeAddress: 'NChangeAddress...',
|
|
33
|
+
toAddress: 'NReceivingAddress...'
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const restrictedAsset = '$SECURITY';
|
|
38
|
+
const ownerToken = `${restrictedAsset}!`;
|
|
39
|
+
|
|
40
|
+
// Step 1: Verify you own the owner token
|
|
41
|
+
console.log('=== Step 1: Verify Owner Token ===\n');
|
|
42
|
+
|
|
43
|
+
const myAssets = await assets.listMyAssets(ownerToken);
|
|
44
|
+
if (!myAssets[ownerToken]) {
|
|
45
|
+
throw new Error(`You must own ${ownerToken} to freeze/unfreeze`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log(`✓ Owner token found: ${ownerToken}`);
|
|
49
|
+
|
|
50
|
+
// Step 2: Freeze specific addresses
|
|
51
|
+
console.log('\n=== Step 2: Freeze Addresses ===\n');
|
|
52
|
+
|
|
53
|
+
const addressesToFreeze = [
|
|
54
|
+
'NAddressToFreeze1...',
|
|
55
|
+
'NAddressToFreeze2...',
|
|
56
|
+
'NAddressToFreeze3...'
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
const freezeResult = await assets.freezeAddresses({
|
|
60
|
+
assetName: restrictedAsset,
|
|
61
|
+
addresses: addressesToFreeze
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
console.log('Addresses frozen successfully!');
|
|
65
|
+
console.log('Asset:', freezeResult.metadata.assetName);
|
|
66
|
+
console.log('Addresses frozen:', freezeResult.metadata.addressCount);
|
|
67
|
+
console.log('Fee:', freezeResult.fee, 'XNA');
|
|
68
|
+
console.log('Burn:', freezeResult.burn, 'XNA (no burn for freeze operations)');
|
|
69
|
+
|
|
70
|
+
console.log('\nFrozen addresses:');
|
|
71
|
+
freezeResult.metadata.targetAddresses.forEach((addr, i) => {
|
|
72
|
+
console.log(`${i + 1}. ${addr}`);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
console.log('\nEffect: These addresses can NO LONGER:');
|
|
76
|
+
console.log('- Send the restricted asset');
|
|
77
|
+
console.log('- Receive the restricted asset');
|
|
78
|
+
console.log('- Trade the restricted asset');
|
|
79
|
+
|
|
80
|
+
// Step 3: Check if address is frozen
|
|
81
|
+
console.log('\n=== Step 3: Verify Freeze Status ===\n');
|
|
82
|
+
|
|
83
|
+
for (const address of addressesToFreeze) {
|
|
84
|
+
const isFrozen = await assets.isAddressFrozen(address, restrictedAsset);
|
|
85
|
+
console.log(`${address}: ${isFrozen ? 'FROZEN ❄️' : 'ACTIVE ✓'}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error('Error freezing addresses:', error.message);
|
|
90
|
+
|
|
91
|
+
if (error.name === 'OwnerTokenNotFoundError') {
|
|
92
|
+
console.error('You need the owner token to freeze addresses');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Example: Unfreeze addresses
|
|
98
|
+
async function unfreezeAddresses() {
|
|
99
|
+
const rpc = async (method, params) => {
|
|
100
|
+
console.log(`RPC Call: ${method}`, params);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const assets = new NeuraiAssets(rpc, {
|
|
104
|
+
network: 'xna',
|
|
105
|
+
addresses: ['NYourAddress1...'],
|
|
106
|
+
changeAddress: 'NChangeAddress...',
|
|
107
|
+
toAddress: 'NReceivingAddress...'
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const restrictedAsset = '$SECURITY';
|
|
112
|
+
const addressesToUnfreeze = [
|
|
113
|
+
'NAddressToUnfreeze1...',
|
|
114
|
+
'NAddressToUnfreeze2...'
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
console.log('=== Unfreezing Addresses ===\n');
|
|
118
|
+
|
|
119
|
+
const result = await assets.unfreezeAddresses({
|
|
120
|
+
assetName: restrictedAsset,
|
|
121
|
+
addresses: addressesToUnfreeze
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
console.log('Addresses unfrozen successfully!');
|
|
125
|
+
console.log('Addresses unfrozen:', result.metadata.addressCount);
|
|
126
|
+
console.log('Fee:', result.fee, 'XNA');
|
|
127
|
+
|
|
128
|
+
console.log('\nThese addresses can now:');
|
|
129
|
+
console.log('- Send the restricted asset');
|
|
130
|
+
console.log('- Receive the restricted asset');
|
|
131
|
+
console.log('- Trade the restricted asset');
|
|
132
|
+
console.log('(if they still meet verifier requirements)');
|
|
133
|
+
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.error('Error unfreezing addresses:', error.message);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Example: Global freeze (freeze entire asset)
|
|
140
|
+
async function freezeAssetGlobally() {
|
|
141
|
+
const rpc = async (method, params) => {
|
|
142
|
+
console.log(`RPC Call: ${method}`, params);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const assets = new NeuraiAssets(rpc, {
|
|
146
|
+
network: 'xna',
|
|
147
|
+
addresses: ['NYourAddress1...'],
|
|
148
|
+
changeAddress: 'NChangeAddress...',
|
|
149
|
+
toAddress: 'NReceivingAddress...'
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const restrictedAsset = '$SECURITY';
|
|
154
|
+
|
|
155
|
+
console.log('=== Global Asset Freeze ===\n');
|
|
156
|
+
console.log('⚠️ WARNING: This will freeze the ENTIRE asset!');
|
|
157
|
+
console.log('ALL addresses will be unable to trade this asset.\n');
|
|
158
|
+
|
|
159
|
+
const result = await assets.freezeAssetGlobally({
|
|
160
|
+
assetName: restrictedAsset
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
console.log('Asset frozen globally!');
|
|
164
|
+
console.log('Asset:', result.metadata.assetName);
|
|
165
|
+
console.log('Operation:', result.metadata.operationType);
|
|
166
|
+
console.log('Fee:', result.fee, 'XNA');
|
|
167
|
+
|
|
168
|
+
console.log('\nEffect:');
|
|
169
|
+
console.log('- ALL addresses are frozen for this asset');
|
|
170
|
+
console.log('- Nobody can send/receive/trade');
|
|
171
|
+
console.log('- Use for emergency situations or regulatory compliance');
|
|
172
|
+
|
|
173
|
+
// Verify global freeze status
|
|
174
|
+
const isGloballyFrozen = await assets.checkGlobalRestriction(restrictedAsset);
|
|
175
|
+
console.log(`\nGlobal freeze status: ${isGloballyFrozen ? 'FROZEN ❄️' : 'ACTIVE ✓'}`);
|
|
176
|
+
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.error('Error freezing asset globally:', error.message);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Example: Global unfreeze (unfreeze entire asset)
|
|
183
|
+
async function unfreezeAssetGlobally() {
|
|
184
|
+
const rpc = async (method, params) => {
|
|
185
|
+
console.log(`RPC Call: ${method}`, params);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const assets = new NeuraiAssets(rpc, {
|
|
189
|
+
network: 'xna',
|
|
190
|
+
addresses: ['NYourAddress1...'],
|
|
191
|
+
changeAddress: 'NChangeAddress...',
|
|
192
|
+
toAddress: 'NReceivingAddress...'
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
const restrictedAsset = '$SECURITY';
|
|
197
|
+
|
|
198
|
+
console.log('=== Global Asset Unfreeze ===\n');
|
|
199
|
+
|
|
200
|
+
const result = await assets.unfreezeAssetGlobally({
|
|
201
|
+
assetName: restrictedAsset
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
console.log('Asset unfrozen globally!');
|
|
205
|
+
console.log('Asset:', result.metadata.assetName);
|
|
206
|
+
console.log('Fee:', result.fee, 'XNA');
|
|
207
|
+
|
|
208
|
+
console.log('\nEffect:');
|
|
209
|
+
console.log('- Global freeze lifted');
|
|
210
|
+
console.log('- Trading resumes for all addresses');
|
|
211
|
+
console.log('- Individual freezes (if any) remain in effect');
|
|
212
|
+
console.log('- Verifier requirements still apply');
|
|
213
|
+
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.error('Error unfreezing asset globally:', error.message);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Example: Complete freeze workflow
|
|
220
|
+
async function completeWorkflow() {
|
|
221
|
+
const rpc = async (method, params) => {
|
|
222
|
+
console.log(`RPC Call: ${method}`, params);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const assets = new NeuraiAssets(rpc, {
|
|
226
|
+
network: 'xna',
|
|
227
|
+
addresses: ['NYourAddress1...'],
|
|
228
|
+
changeAddress: 'NChangeAddress...',
|
|
229
|
+
toAddress: 'NReceivingAddress...'
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
const restrictedAsset = '$SECURITY';
|
|
234
|
+
const suspiciousAddress = 'NSuspiciousAddress...';
|
|
235
|
+
|
|
236
|
+
console.log('=== Complete Freeze/Unfreeze Workflow ===\n');
|
|
237
|
+
|
|
238
|
+
// Scenario: Detect suspicious activity
|
|
239
|
+
console.log('Scenario: Suspicious activity detected on address');
|
|
240
|
+
console.log(`Address: ${suspiciousAddress}\n`);
|
|
241
|
+
|
|
242
|
+
// Step 1: Freeze the suspicious address
|
|
243
|
+
console.log('Step 1: Freeze suspicious address');
|
|
244
|
+
await assets.freezeAddresses({
|
|
245
|
+
assetName: restrictedAsset,
|
|
246
|
+
addresses: [suspiciousAddress]
|
|
247
|
+
});
|
|
248
|
+
console.log('✓ Address frozen\n');
|
|
249
|
+
|
|
250
|
+
// Step 2: Verify freeze status
|
|
251
|
+
console.log('Step 2: Verify freeze status');
|
|
252
|
+
const isFrozen = await assets.isAddressFrozen(suspiciousAddress, restrictedAsset);
|
|
253
|
+
console.log(`Status: ${isFrozen ? 'FROZEN ❄️' : 'ACTIVE ✓'}\n`);
|
|
254
|
+
|
|
255
|
+
// Step 3: Investigate...
|
|
256
|
+
console.log('Step 3: Investigation period...\n');
|
|
257
|
+
|
|
258
|
+
// Step 4: If cleared, unfreeze
|
|
259
|
+
console.log('Step 4: Investigation complete - address cleared');
|
|
260
|
+
await assets.unfreezeAddresses({
|
|
261
|
+
assetName: restrictedAsset,
|
|
262
|
+
addresses: [suspiciousAddress]
|
|
263
|
+
});
|
|
264
|
+
console.log('✓ Address unfrozen\n');
|
|
265
|
+
|
|
266
|
+
// Step 5: Verify unfreeze
|
|
267
|
+
console.log('Step 5: Verify final status');
|
|
268
|
+
const isFrozenAfter = await assets.isAddressFrozen(suspiciousAddress, restrictedAsset);
|
|
269
|
+
console.log(`Status: ${isFrozenAfter ? 'FROZEN ❄️' : 'ACTIVE ✓'}\n`);
|
|
270
|
+
|
|
271
|
+
console.log('Workflow completed successfully!');
|
|
272
|
+
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error('Error in workflow:', error.message);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Run the examples
|
|
279
|
+
console.log('=== Example 1: Freeze Specific Addresses ===\n');
|
|
280
|
+
freezeAddresses();
|
|
281
|
+
|
|
282
|
+
console.log('\n\n=== Example 2: Unfreeze Addresses ===\n');
|
|
283
|
+
unfreezeAddresses();
|
|
284
|
+
|
|
285
|
+
console.log('\n\n=== Example 3: Global Freeze ===\n');
|
|
286
|
+
freezeAssetGlobally();
|
|
287
|
+
|
|
288
|
+
console.log('\n\n=== Example 4: Global Unfreeze ===\n');
|
|
289
|
+
unfreezeAssetGlobally();
|
|
290
|
+
|
|
291
|
+
console.log('\n\n=== Example 5: Complete Workflow ===\n');
|
|
292
|
+
completeWorkflow();
|