Bitcoin transactions with genesis metadata represent the creation of a new CoinSpark asset.

The genesis metadata is encoded in a transaction’s first OP_RETURN output following CoinSpark’s general metadata format. Unless it is combined with other CoinSpark metadata, the prefix will be SPKg (0x53 0x50 0x4B 0x67).

So long as the transaction has a sufficient transaction fee (collected by miners), the units created of the asset are ‘deposited’ in all of the transaction’s non-OP_RETURN outputs except the last.

You can easily encode and extract CoinSpark genesis metadata using the appropriate CoinSpark library for your programming language.

CoinSparkGenesis fields

A CoinSparkGenesis structure or object contains the following fields:

  • qtyMantissa – mantissa of the number of units being created, between 1 and 1000.
  • qtyExponent – base 10 exponent of the number of units being created, between 0 and 11.
  • chargeFlatMantissa – mantissa of the fixed transaction charge, between 0 and 100 (max 50 if chargeFlatExponent is 2).
  • chargeFlatExponent – base 10 exponent of the fixed transaction charge, between 0 and 2.
  • chargeBasisPoints – number of basis points (hundredths of a percent) of proportional transaction charge, between 0 and 250.
  • useHttps – boolean flag for whether the asset web page should be accessed using the https:// scheme.
  • domainName – domain name of the asset web page (see asset web pages for how the full URL is calculated).
  • usePrefix – boolean flag for whether the asset web page URL should include the coinspark/ prefix.
  • pagePath – additional path of the asset web page URL, characters from a-z, 0-9, . and - only.
  • assetHash – SHA-256 hash of key information relating to the asset (see asset hashes for more information).
  • assetHashLen – length of prefix of assetHash which is relevant for encoding or comparison.

The qtyMantissa and qtyExponent fields are combined according to the formula qtyMantissa*pow(10, qtyExponent) to create a final quantity between 1 and 1014 with 3 significant digits of accuracy. Similarly, the chargeFlatMantissa and chargeFlatExponent fields are combined according to the formula chargeFlatMantissa*pow(10, chargeFlatExponent) to create a final flat charge between 0 and 5,000 asset units with 2 significant digits of accuracy. See examples below for easy ways to get and set these fields.

Creating and encoding genesis metadata

C/C++

CoinSparkGenesis genesis;
CoinSparkAssetQty actualQty, actualChargeFlat;
char metadata[40]; // 40 byte limit for OP_RETURNs
size_t metadataLen;

CoinSparkGenesisSetQty(&genesis, 1234567, 1); // 1234567 units rounded up
actualQty=CoinSparkGenesisGetQty(&genesis); // can check final quantity assigned

CoinSparkGenesisSetChargeFlat(&genesis, 4321, 0); // 4321 units rounded to nearest
actualChargeFlat=CoinSparkGenesisGetChargeFlat(&genesis); // can check final flat charge assigned
genesis.chargeBasisPoints=10; // additional 0.1% per payment

genesis.useHttps=FALSE;
strcpy(genesis.domainName, "www.example.com");
genesis.usePrefix=TRUE;
strcpy(genesis.pagePath, "usd-1");

CoinSparkCalcAssetHash(..., genesis.assetHash); // see 'Asset Hashes' docs page
genesis.assetHashLen=CoinSparkGenesisCalcHashLen(&genesis, 40); // 40 byte limit for OP_RETURN

metadataLen=CoinSparkGenesisEncode(&genesis, metadata, 40);

if (metadataLen)
    ; // use CoinSparkMetadataToScript() to embed metadata (length metadataLen) in an output script
else
    ; // handle error

Java

CoinSparkGenesis genesis=new CoinSparkGenesis();

genesis.setQty(1234567, 1); // 1234567 units rounded up     
long actualQty=genesis.getQty(); // can check final quantity assigned

genesis.setChargeFlat(4321, 0); // 4321 units rounded to nearest
long actualChargeFlat=genesis.getChargeFlat(); // can check final flat charge assigned

genesis.setChargeBasisPoints((short)10); // additional 0.1% per payment

genesis.setUseHttps(false);
genesis.setDomainName("www.example.com");
genesis.setUsePrefix(true);
genesis.setPagePath("usd-1");

genesis.setAssetHash(CoinSparkGenesis.calcAssetHash(...)); // see 'Asset Hashes' docs page
genesis.setAssetHashLen(genesis.calcHashLen(40)); // 40 byte limit for OP_RETURN

byte[] metadata=genesis.encode(40);

if (metadata!=null)
    ; // use CoinSparkBase.metadataToScript() to embed metadata in an output script
else
    ; // handle error

Javascript

var genesis=new CoinSparkGenesis();

genesis.setQty(1234567, 1); // 1234567 units rounded up
var actualQty=genesis.getQty(); // can check final quantity assigned

genesis.setChargeFlat(4321, 0); // 4321 units rounded to nearest
var actualChargeFlat=genesis.getChargeFlat(); // can check final flat charge assigned
genesis.chargeBasisPoints=10; // additional 0.1% per payment

genesis.useHttps=false;
genesis.domainName="www.example.com";
genesis.usePrefix=true;
genesis.pagePath="usd-1";

genesis.assetHash=CoinSparkCalcAssetHash(...); // see 'Asset Hashes' docs page
genesis.assetHashLen=genesis.calcHashLen(40); // 40 byte limit for OP_RETURN

var metadata=genesis.encode(40);

if (metadata)
    ; // use CoinSparkMetadataToScript() to embed metadata in an output script
else
    ; // handle error

PHP

$genesis=new CoinSparkGenesis();

$genesis->setQty(1234567, 1); // 1234567 units rounded up
$actualQty=genesis->getQty(); // can check final quantity assigned

$genesis->setChargeFlat(4321, 0); // 4321 units rounded to nearest
$actualChargeFlat=genesis->getChargeFlat(); // can check final flat charge assigned
$genesis->chargeBasisPoints=10; // additional 0.1% per payment

$genesis->useHttps=false;
$genesis->domainName="www.example.com";
$genesis->usePrefix=true;
$genesis->pagePath="usd-1";

$genesis->assetHash=CoinSparkCalcAssetHash(...); // see 'Asset Hashes' docs page
$genesis->assetHashLen=$genesis->calcHashLen(40); // 40 byte limit for OP_RETURN

$metadata=$genesis->encode(40);

if (isset($metadata))
    ; // use CoinSparkMetadataToScript() to embed $metadata in an output script
else
    ; // handle error

Python

genesis=CoinSparkGenesis()

genesis.setQty(1234567, 1) # 1234567 units rounded up     
actualQty=genesis.getQty() # can check final quantity assigned

genesis.setChargeFlat(4321, 0) # 4321 units rounded to nearest
actualChargeFlat=genesis.getChargeFlat() # can check final flat charge assigned
genesis.chargeBasisPoints=10 # additional 0.1% per payment

genesis.useHttps=False
genesis.domainName="www.example.com"
genesis.usePrefix=True
genesis.pagePath="usd-1"

genesis.assetHash=CoinSparkCalcAssetHash(...) # see 'Asset Hashes' docs page
genesis.assetHashLen=genesis.calcHashLen(40) # 40 byte limit for OP_RETURN

metadata=genesis.encode(40)

if not metadata is None:
     # use CoinSparkMetadataToScript() to embed metadata in an output script
else:
     # handle error

Ruby

genesis=CoinSparkGenesis.new

genesis.setQty(1234567, 1) # 1234567 units rounded up     
actualQty=genesis.getQty # can check final quantity assigned

genesis.setChargeFlat(4321, 0) # 4321 units rounded to nearest
actualChargeFlat=genesis.getChargeFlat # can check final flat charge assigned
genesis.chargeBasisPoints=10 # additional 0.1% per payment

genesis.useHttps=false
genesis.domainName="www.example.com"
genesis.usePrefix=true
genesis.pagePath="usd-1"

genesis.assetHash=CoinSparkCalcAssetHash(...) # see 'Asset Hashes' docs page
genesis.assetHashLen=genesis.calcHashLen(40) # 40 byte limit for OP_RETURN

metadata=genesis.encode(40)

if metadata!=nil
     # use CoinSparkMetadataToScript() to embed metadata in an output script
else
     # handle error
end

Extracting and decoding genesis metadata

Please see the general metadata sample code.