@@ -74,31 +74,45 @@ export async function createCLI() {
7474 chalk . cyan ( "libp2p node started. Waiting for peer connections..." )
7575 ) ;
7676
77- // Wait for at least one active P2P connection before running commands
77+ // Wait for the TARGET peer (the one in NODE_URL) to be connected,
78+ // not just any bootstrap peer — otherwise signed commands fail with
79+ // "Cannot reach peer ...".
80+ const targetPeerId = isFullMultiaddr
81+ ? nodeUrl . split ( "/p2p/" ) . pop ( ) !
82+ : nodeUrl ;
7883 const maxWait = 20_000 ;
7984 const interval = 500 ;
8085 let waited = 0 ;
8186 const libp2p = ( ProviderInstance as any ) . p2pProvider ?. libp2pNode ;
87+ const isTargetConnected = ( ) =>
88+ ( libp2p ?. getPeers ( ) ?? [ ] ) . some (
89+ ( p : { toString ( ) : string } ) => p . toString ( ) === targetPeerId
90+ ) ;
8291 while ( waited < maxWait ) {
83- const conns = libp2p ?. getConnections ( ) ?. length ?? 0 ;
84- if ( conns > 0 ) {
92+ if ( isTargetConnected ( ) ) {
93+ const total = libp2p ?. getConnections ( ) ?. length ?? 0 ;
8594 console . log (
86- chalk . green ( `Connected to ${ conns } peer(s) in ${ waited } ms` )
95+ chalk . green (
96+ `Connected to target peer ${ targetPeerId . slice ( 0 , 12 ) } … in ${ waited } ms (total peers: ${ total } )`
97+ )
8798 ) ;
8899 break ;
89100 }
90101 await new Promise ( ( r ) => setTimeout ( r , interval ) ) ;
91102 waited += interval ;
92103 if ( waited % 3000 === 0 ) {
104+ const total = libp2p ?. getConnections ( ) ?. length ?? 0 ;
93105 console . log (
94- chalk . yellow ( ` Still waiting for peers... (${ waited / 1000 } s)` )
106+ chalk . yellow (
107+ ` Waiting for target peer ${ targetPeerId . slice ( 0 , 12 ) } … (${ waited / 1000 } s, ${ total } other peer(s))`
108+ )
95109 ) ;
96110 }
97111 }
98- if ( ( libp2p ?. getConnections ( ) ?. length ?? 0 ) === 0 ) {
112+ if ( ! isTargetConnected ( ) ) {
99113 console . error (
100114 chalk . red (
101- `No P2P peers connected after ${ maxWait / 1000 } s. Commands may fail.`
115+ `Target peer ${ targetPeerId } not reachable after ${ maxWait / 1000 } s. Commands will fail.`
102116 )
103117 ) ;
104118 }
@@ -802,5 +816,69 @@ export async function createCLI() {
802816 ] ) ;
803817 } ) ;
804818
819+ program
820+ . command ( "createBucket" )
821+ . description ( "Create a new persistent-storage bucket gated by a single access list (chain inferred from RPC)" )
822+ . argument ( "<accessListAddress>" , "Access list contract address (0x…)" )
823+ . action ( async ( accessListAddress ) => {
824+ const { signer, chainId } = await initializeSigner ( ) ;
825+ const commands = new Commands ( signer , chainId ) ;
826+ await commands . createBucket ( [ null , accessListAddress ] ) ;
827+ } ) ;
828+
829+ program
830+ . command ( "addFileToBucket" )
831+ . description ( "Upload a local file into a bucket" )
832+ . argument ( "<bucketId>" , "Bucket id" )
833+ . argument ( "<filePath>" , "Path to local file" )
834+ . argument ( "[fileName]" , "Name under which to store the file (defaults to basename)" )
835+ . action ( async ( bucketId , filePath , fileName ) => {
836+ const { signer, chainId } = await initializeSigner ( ) ;
837+ const commands = new Commands ( signer , chainId ) ;
838+ await commands . addFileToBucket ( [ null , bucketId , filePath , fileName ] ) ;
839+ } ) ;
840+
841+ program
842+ . command ( "listBuckets" )
843+ . description ( "List buckets owned by an address (defaults to signer)" )
844+ . option ( "-o, --owner <address>" , "Owner address" )
845+ . action ( async ( options ) => {
846+ const { signer, chainId } = await initializeSigner ( ) ;
847+ const commands = new Commands ( signer , chainId ) ;
848+ await commands . listBuckets ( [ null , options . owner ] ) ;
849+ } ) ;
850+
851+ program
852+ . command ( "listFilesInBucket" )
853+ . description ( "List files in a bucket" )
854+ . argument ( "<bucketId>" , "Bucket id" )
855+ . action ( async ( bucketId ) => {
856+ const { signer, chainId } = await initializeSigner ( ) ;
857+ const commands = new Commands ( signer , chainId ) ;
858+ await commands . listFilesInBucket ( [ null , bucketId ] ) ;
859+ } ) ;
860+
861+ program
862+ . command ( "getFileObject" )
863+ . description ( "Get the file-object descriptor for a file in a bucket" )
864+ . argument ( "<bucketId>" , "Bucket id" )
865+ . argument ( "<fileName>" , "File name" )
866+ . action ( async ( bucketId , fileName ) => {
867+ const { signer, chainId } = await initializeSigner ( ) ;
868+ const commands = new Commands ( signer , chainId ) ;
869+ await commands . getFileObject ( [ null , bucketId , fileName ] ) ;
870+ } ) ;
871+
872+ program
873+ . command ( "deleteFile" )
874+ . description ( "Delete a file from a bucket" )
875+ . argument ( "<bucketId>" , "Bucket id" )
876+ . argument ( "<fileName>" , "File name" )
877+ . action ( async ( bucketId , fileName ) => {
878+ const { signer, chainId } = await initializeSigner ( ) ;
879+ const commands = new Commands ( signer , chainId ) ;
880+ await commands . deleteFile ( [ null , bucketId , fileName ] ) ;
881+ } ) ;
882+
805883 return program ;
806884}
0 commit comments