metaboss

appreciate metaboss update to 0.10.3 with new support for max-editions and use parameters. while online portals are convenient, they pose a challenge to automating the minting:

metaboss mint one --keypair <> --external-metadata-uri <> --sign --primary-sale-happened --max-editions 75

Advertisement

printing NFTs on Solana

printing NFTs on Solana will unlock the next wave of play-to-earn, play-and-earn, and next play-to-own.

great writeup on the opportunities in this space well laid out https://sebornstein.substack.com/p/no-ape-ologies-1?sd=pf

experimented more with Metaplex and it’s refactored libraries for smoother NFT handling, including retrieval of JSON metadata. new metaplex/J’s v14.0 cleaned up the flow alot with it’s dynamic adapters:

thus by 20 lines of code including import statements, we Print a new NFT from Master edition directly into recipient wallet. in terms of a P2O game, the operator owns the catalogue, prints to Player wallets, and let’s Players trade freely on secondary market.

spl-token transfer

Finally breakthrough in spl-token transfer of a Solana minted token from wallet A to wallet B. The technical details are not difficult but (1) the dated documentation of older working libs and (2) rapidly changing Solana libraries lack clarity.

In this case, attempting to move a PRGC token. We know its address public key. Available source code always assumes the destination token address is newly generated (keypair.generate()), while in this trail the assumption is the destination wallet already exists:

  let prgcMintPublicKey = "66edZnAPEJSxnAK4SckuupssXpbu5doV57FUcghaqPsY";
  const mintPublicKey = new PublicKey(prgcMintPublicKey);  
  var mintToken = new Token(
    connection,
    mintPublicKey,
    TOKEN_PROGRAM_ID,
    sourceWallet
  );

  const fromTokenAccount = await mintToken.getOrCreateAssociatedAccountInfo(
     sourceWallet.publicKey
  );

  var destWallet = new PublicKey("<some dest wallet>"); 

  const account = await connection.getTokenAccountsByOwner(destWallet, { 
      mint: mintPublicKey
   });
  var destTokenAccount = account.value[0].pubkey;  //needs index check, else create

  let tx = new Transaction().add(
     Token.createTransferInstruction(
      TOKEN_PROGRAM_ID,
      fromTokenAccount.address,
      destTokenAccount,
      sourceWallet.publicKey,
      [],
      amount
    )
  );
  tx.feePayer = sourceWallet.publicKey;

  const txhash = await sendAndConfirmTransaction(connection, tx, [sourceWallet]);

It takes bit of time to appreicate the “Token Account” sub-structure of Solana. In this case, we identify the destTokenAccountv directly by filtering on the mint public key.

Obviously, sourceWallet must have private key for signing. I’ll refactor to offload this key management into the Hashicorp Vault Solana Plugin extension with an API call for signing transaction.

hashicorp vault solana plugin

challenge in protecting crypto keys is the private key, and specifically its key management. short of enterprise approach of formal custodians, there exist alternatives including simply adopting industry best practises of key vaulting. certainly, nobody would want to hold private keys in databases or code.

it seemed Hashicorp Vault does a great job at protecting secrets (at scale). BTC and ETH have their public published Vault Plugin, with varying features:

while the ETH feature to push to blockchain is neat, it creates a layer of complexity in that a full stack developer would assume to use Vault “..as-a-service”, and not necessarily want to go dig around Vault’s logs for any troubleshooting / debugging on broadcasting to the network. code might also want to run some final sense checks prior to pushing out the transaction.

as result, Ive had great engineering support in commissioning a Hashicorp Vault Solana Plugin:

  • Path: {{vault_server}}/v1/vault-plugin-secrets-solana/key on HTTP Method: GET to return a users public key
  • PATH: {{vault_server}}/v1/vault-plugin-secrets-solana/sign HTTP Method: POST to sign a transaction within the Vault

The Solana Plugin does some other cool stuff too, though I’ll keep that redacted for now.

tinkering on solana

to keep current, tinkering on web3 and it’s interaction with Solana

real impressed how JavaScript, bring run inside nodejs, or libs served via http to browser, create a seamless interactions across the tiers. implementing libs of Solana, Metaplax, Arweave and web3 calls to perform transactions surprisingly easy. odd however to have npm and yarn compete in similar functionality

a small criticism on Solana that whilst it’s exploded as an ecosystem, it’s developer community still feels fledging and alot of code seems incomplete. example of minting an NFT is described 1000x using CandyMachine (now v2) whilst near no code examples exist on how to create that same NFT in .js.

architecting a stack using HashiCorp Vault for protecting secrets, Solana Plugin for Vault to manage keys + sign transactions, and KeyCloak to manage identities using OIDC. this approach to ensure only public keys of authorized users returned by authenticated calls to Vaukt. pieces are falling together nicely.

sneaky /dev/sd*

umbrel kept going offline. it seemed power related. more fustrating when Linux devices to assign /dev/sd* devices at random for USB storage. bitcoin-core nor umbrel appreciated booting without expected paths.

took a while to figure out pre-defining the devide assignment based on USB stoage “model name”. hdparam reveals the full model name string on the now reassigned device

~$ sudo hdparm -I /dev/sdb

located this guidance to assign the device in udev based on a string match:

~$ vi /etc/udev/rules.d/00-corrections.rules

KERNEL=="sd?", ATTRS{model}=="SAMSUNG SP0411N", NAME="sda"
KERNEL=="sd??", ATTRS{model}=="SAMSUNG SP0411N", NAME="sda%n"

worked wonderfully. back up and running. resumed sync’ing txns from 5 years ago…