@@ -27,7 +27,9 @@ import {
2727 sendTx ,
2828 unitsToAmount ,
2929 EscrowContract ,
30- getTokenDecimals
30+ getTokenDecimals ,
31+ AccesslistFactory ,
32+ AccessListContract
3133} from "@oceanprotocol/lib" ;
3234import { Asset } from '@oceanprotocol/ddo-js' ;
3335import { Signer , ethers , getAddress } from "ethers" ;
@@ -729,6 +731,7 @@ export class Commands {
729731 )
730732 console . log ( "Verifying payment..." ) ;
731733 await new Promise ( resolve => setTimeout ( resolve , 3000 ) )
734+
732735 const validationEscrow = await escrow . verifyFundsForEscrowPayment (
733736 paymentToken ,
734737 computeEnv . consumerAddress ,
@@ -791,10 +794,10 @@ export class Commands {
791794 null ,
792795 null ,
793796 // additionalDatasets, only c2d v1
794- output ,
797+ output
795798 ) ;
796799
797- console . log ( "compute jobs : " , computeJobs ) ;
800+ console . log ( "computeJobs : " , computeJobs ) ;
798801
799802 if ( computeJobs && computeJobs [ 0 ] ) {
800803 const { jobId, payment } = computeJobs [ 0 ] ;
@@ -1454,4 +1457,176 @@ export class Commands {
14541457
14551458 return authorizations ;
14561459 }
1460+
1461+ public async createAccessList ( args : string [ ] ) : Promise < void > {
1462+ try {
1463+ const name = args [ 0 ] ;
1464+ const symbol = args [ 1 ] ;
1465+ const transferable = args [ 2 ] === 'true' ;
1466+ const initialUsers = args [ 3 ] ? args [ 3 ] . split ( ',' ) . map ( u => u . trim ( ) ) : [ ] ;
1467+
1468+ if ( ! name || ! symbol ) {
1469+ console . error ( chalk . red ( 'Name and symbol are required' ) ) ;
1470+ return ;
1471+ }
1472+
1473+ const config = await getConfigByChainId ( Number ( this . config . chainId ) ) ;
1474+ if ( ! config . AccessListFactory ) {
1475+ console . error ( chalk . red ( 'Access list factory not found. Check local address.json file' ) ) ;
1476+ return ;
1477+ }
1478+ const accessListFactory = new AccesslistFactory (
1479+ config . AccessListFactory ,
1480+ this . signer ,
1481+ Number ( this . config . chainId )
1482+ ) ;
1483+
1484+ const owner = await this . signer . getAddress ( ) ;
1485+ const tokenURIs = initialUsers . map ( ( ) => 'https://oceanprotocol.com/nft/' ) ;
1486+
1487+ console . log ( chalk . cyan ( 'Creating new access list...' ) ) ;
1488+ console . log ( `Name: ${ name } ` ) ;
1489+ console . log ( `Symbol: ${ symbol } ` ) ;
1490+ console . log ( `Transferable: ${ transferable } ` ) ;
1491+ console . log ( `Owner: ${ owner } ` ) ;
1492+ console . log ( `Initial users: ${ initialUsers . length > 0 ? initialUsers . join ( ', ' ) : 'none' } ` ) ;
1493+
1494+ const accessListAddress = await accessListFactory . deployAccessListContract (
1495+ name ,
1496+ symbol ,
1497+ tokenURIs ,
1498+ transferable ,
1499+ owner ,
1500+ initialUsers
1501+ ) ;
1502+
1503+ console . log ( chalk . green ( `\nAccess list created successfully!` ) ) ;
1504+ console . log ( chalk . green ( `Contract address: ${ accessListAddress } ` ) ) ;
1505+ } catch ( error ) {
1506+ console . error ( chalk . red ( 'Error creating access list:' ) , error ) ;
1507+ }
1508+ }
1509+
1510+ public async addToAccessList ( args : string [ ] ) : Promise < void > {
1511+ try {
1512+ const accessListAddress = args [ 0 ] ;
1513+ const users = args [ 1 ] . split ( ',' ) . map ( u => u . trim ( ) ) ;
1514+
1515+ if ( ! accessListAddress || users . length === 0 ) {
1516+ console . error ( chalk . red ( 'Access list address and at least one user are required' ) ) ;
1517+ return ;
1518+ }
1519+
1520+ const accessList = new AccessListContract (
1521+ accessListAddress ,
1522+ this . signer ,
1523+ Number ( this . config . chainId )
1524+ ) ;
1525+
1526+ console . log ( chalk . cyan ( `Adding ${ users . length } user(s) to access list...` ) ) ;
1527+
1528+ if ( users . length === 1 ) {
1529+ const tx = await accessList . mint ( users [ 0 ] , 'https://oceanprotocol.com/nft/' ) ;
1530+ await tx . wait ( ) ;
1531+ console . log ( chalk . green ( `Successfully added user ${ users [ 0 ] } to access list` ) ) ;
1532+ return ;
1533+ }
1534+
1535+ const tokenURIs = users . map ( ( ) => 'https://oceanprotocol.com/nft/' ) ;
1536+ const tx = await accessList . batchMint ( users , tokenURIs ) ;
1537+ await tx . wait ( ) ;
1538+ console . log ( chalk . green ( `Successfully added ${ users . length } users to access list:` ) ) ;
1539+ users . forEach ( user => console . log ( ` - ${ user } ` ) ) ;
1540+ } catch ( error ) {
1541+ console . error ( chalk . red ( 'Error adding users to access list:' ) , error ) ;
1542+ }
1543+ }
1544+
1545+
1546+ public async checkAccessList ( args : string [ ] ) : Promise < void > {
1547+ try {
1548+ const accessListAddress = args [ 0 ] ;
1549+ const users = args [ 1 ] . split ( ',' ) . map ( u => u . trim ( ) ) ;
1550+
1551+ if ( ! accessListAddress || users . length === 0 ) {
1552+ console . error ( chalk . red ( 'Access list address and at least one user are required' ) ) ;
1553+ return ;
1554+ }
1555+
1556+ const accessList = new AccessListContract (
1557+ accessListAddress ,
1558+ this . signer ,
1559+ Number ( this . config . chainId )
1560+ ) ;
1561+
1562+ console . log ( chalk . cyan ( `Checking access list for ${ users . length } user(s)...\n` ) ) ;
1563+
1564+ for ( const user of users ) {
1565+ const balance = await accessList . balance ( user ) ;
1566+ const hasAccess = Number ( balance ) > 0 ;
1567+
1568+ if ( hasAccess ) {
1569+ console . log ( chalk . green ( `✓ ${ user } : Has access (balance: ${ balance } )` ) ) ;
1570+ } else {
1571+ console . log ( chalk . red ( `✗ ${ user } : No access` ) ) ;
1572+ }
1573+ }
1574+ } catch ( error ) {
1575+ console . error ( chalk . red ( 'Error checking access list:' ) , error ) ;
1576+ }
1577+ }
1578+
1579+
1580+ public async removeFromAccessList ( args : string [ ] ) : Promise < void > {
1581+ try {
1582+ const accessListAddress = args [ 0 ] ;
1583+ const users = args [ 1 ] . split ( ',' ) . map ( u => u . trim ( ) ) ;
1584+
1585+ if ( ! accessListAddress || users . length === 0 ) {
1586+ console . error ( chalk . red ( 'Access list address and at least one user address are required' ) ) ;
1587+ return ;
1588+ }
1589+
1590+ const accessList = new AccessListContract (
1591+ accessListAddress ,
1592+ this . signer ,
1593+ Number ( this . config . chainId )
1594+ ) ;
1595+
1596+ console . log ( chalk . cyan ( `Removing ${ users . length } user(s) from access list...` ) ) ;
1597+ for ( const user of users ) {
1598+ const balance = await accessList . balance ( user ) ;
1599+
1600+ if ( Number ( balance ) === 0 ) {
1601+ console . log ( chalk . yellow ( `⚠ User ${ user } is not on the access list, skipping...` ) ) ;
1602+ continue ;
1603+ }
1604+
1605+ const balanceNum = Number ( balance ) ;
1606+ const contract = accessList . contract ;
1607+
1608+ let removedCount = 0 ;
1609+ for ( let index = 0 ; index < balanceNum ; index ++ ) {
1610+ try {
1611+ const tokenId = await contract . tokenOfOwnerByIndex ( user , index ) ;
1612+ const tx = await accessList . burn ( Number ( tokenId ) ) ;
1613+ await tx . wait ( ) ;
1614+
1615+ console . log ( chalk . green ( `✓ Successfully removed user ${ user } (token ID: ${ tokenId } )` ) ) ;
1616+ removedCount ++ ;
1617+ } catch ( e : any ) {
1618+ console . log ( chalk . yellow ( `⚠ Could not remove token at index ${ index } for user ${ user } : ${ e . message } ` ) ) ;
1619+ }
1620+ }
1621+
1622+ if ( removedCount === 0 ) {
1623+ console . log ( chalk . yellow ( `⚠ Could not remove any tokens for user ${ user } ` ) ) ;
1624+ } else if ( removedCount < balanceNum ) {
1625+ console . log ( chalk . yellow ( `⚠ Only removed ${ removedCount } of ${ balanceNum } tokens for user ${ user } ` ) ) ;
1626+ }
1627+ }
1628+ } catch ( error ) {
1629+ console . error ( chalk . red ( 'Error removing users from access list:' ) , error ) ;
1630+ }
1631+ }
14571632}
0 commit comments