bsv-bap 0.1.17 → 0.1.18

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bsv-bap",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "BAP npm module",
5
5
  "repository": {
6
6
  "type": "git",
package/src/cli.ts CHANGED
File without changes
package/dist/index.cjs DELETED
@@ -1,8 +0,0 @@
1
- // @bun @bun-cjs
2
- (function(exports, require, module, __filename, __dirname) {var{defineProperty:v,getOwnPropertyNames:r,getOwnPropertyDescriptor:a}=Object,e=Object.prototype.hasOwnProperty;var K=new WeakMap,t=(j)=>{var J=K.get(j),$;if(J)return J;if(J=v({},"__esModule",{value:!0}),j&&typeof j==="object"||typeof j==="function")r(j).map((q)=>!e.call(J,q)&&v(J,q,{get:()=>j[q],enumerable:!($=a(j,q))||$.enumerable}));return K.set(j,J),J};var jj=(j,J)=>{for(var $ in J)v(j,$,{get:J[$],enumerable:!0,configurable:!0,set:(q)=>J[$]=()=>q})};var Fj={};jj(Fj,{MemberID:()=>x,MasterID:()=>V,BAP:()=>i});module.exports=t(Fj);var L=require("@bsv/sdk"),s=require("@bsv/sdk");var Jj=async(j,J,$,q)=>{let z=`${$}${j}`;return(await fetch(z,{method:"post",headers:{"Content-type":"application/json; charset=utf-8",token:q,format:"json"},body:JSON.stringify(J)})).json()},N=(j,J)=>async($,q)=>{return Jj($,q,j,J)};var m=require("@bsv/sdk"),{toHex:c,toArray:b}=m.Utils,k="1BAPSuaPnfGnSBM3GLV9yhxUdYe4vGbdMT",p=c(b(k)),E="15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva",Uj=c(b(E)),S="https://api.sigmaidentity.com/v1",M=2147483647,R="m/424150'/0'/0'",F=`m/424150'/${M}'/${M}'`;var H="1-bap-identity",h=2,P="friend";var w=require("@bsv/sdk");var U={getRandomBytes(j=32){if(typeof globalThis<"u"&&globalThis.crypto&&globalThis.crypto.getRandomValues){let J=new Uint8Array(j);return globalThis.crypto.getRandomValues(J),J}throw Error("Secure random number generation not available. crypto.getRandomValues() is required for cryptographic operations. This environment may not be suitable for secure key generation.")},getRandomString(j=32){let J=this.getRandomBytes(j);return Array.from(J,($)=>$.toString(16).padStart(2,"0")).join("")},getSigningPathFromHex(j,J=!0){let $="m",q=j.match(/.{1,8}/g);if(!q)throw Error("Invalid hex string");let z=2147483647;for(let Q of q){let W=Number(`0x${Q}`);if(W>z)W-=z;$+=`/${W}${J?"'":""}`}return $},getNextIdentityPath(j){let J=j.split("/"),$=J[J.length-2],q=!1;if($.match("'"))q=!0;let z=(Number($.replace(/[^0-9]/g,""))+1).toString();return J[J.length-2]=z+(q?"'":""),J[J.length-1]=`0${q?"'":""}`,J.join("/")},getNextPath(j){let J=j.split("/"),$=J[J.length-1],q=!1;if($.match("'"))q=!0;let z=(Number($.replace(/[^0-9]/g,""))+1).toString();return J[J.length-1]=z+(q?"'":""),J.join("/")}};var f=require("@bsv/sdk");var Y=require("@bsv/sdk");var{toArray:O,toUTF8:$j,toBase64:qj}=Y.Utils,{magicHash:zj}=Y.BSM,{electrumDecrypt:Qj,electrumEncrypt:Zj}=Y.ECIES;class T{identityAttributes={};signWithBSM(j,J){let $=J.toPublicKey().toAddress(),q=Y.BSM.sign(j,J,"raw"),z=new Y.BigNumber(zj(j)),Q=q.CalculateRecoveryFactor(J.toPublicKey(),z),W=Y.BSM.sign(j,J,"raw").toCompact(Q,!0,"base64");return{address:$,signature:W}}encrypt(j,J){let{privKey:$,pubKey:q}=this.getEncryptionKey(),z=J?Y.PublicKey.fromString(J):q;return qj(Zj(O(j),z,$))}decrypt(j,J){let{privKey:$}=this.getEncryptionKey(),q;if(J)q=Y.PublicKey.fromString(J);return $j(Qj(O(j,"base64"),$,q))}signOpReturnWithAIP(j,J){let $=this.getAIPMessageBuffer(j),{address:q,signature:z}=this.signMessage($.flat(),J);return this.formatAIPOutput($,q,z)}getAttributes(){return this.identityAttributes}getAttribute(j){if(this.identityAttributes[j])return this.identityAttributes[j];return null}setAttribute(j,J){if(!J)return;if(this.identityAttributes[j])this.updateExistingAttribute(j,J);else this.createNewAttribute(j,J)}unsetAttribute(j){delete this.identityAttributes[j]}addAttribute(j,J,$=""){let q=$;if(!$)q=U.getRandomString();this.identityAttributes[j]={value:J,nonce:q}}getAttributeUrns(){let j="";for(let J in this.identityAttributes){let $=this.getAttributeUrn(J);if($)j+=`${$}
3
- `}return j}getAttributeUrn(j){let J=this.identityAttributes[j];if(J)return`urn:bap:id:${j}:${J.value}:${J.nonce}`;return null}parseStringUrns(j){let J={},$=j.replace(/^\s+/g,"").replace(/\r/gm,"").split(`
4
- `);for(let q of $){let Q=q.replace(/^\s+/g,"").replace(/\s+$/g,"").split(":");if(Q[0]==="urn"&&Q[1]==="bap"&&Q[2]==="id"&&Q[3]&&Q[4]&&Q[5])J[Q[3]]={value:Q[4],nonce:Q[5]}}return J}parseAttributes(j){if(typeof j==="string")return this.parseStringUrns(j);for(let J in j)if(!j[J].value||!j[J].nonce)throw Error("Invalid identity attribute");return j||{}}updateExistingAttribute(j,J){if(typeof J==="string"){this.identityAttributes[j].value=J;return}if(this.identityAttributes[j].value=J.value||"",J.nonce)this.identityAttributes[j].nonce=J.nonce}createNewAttribute(j,J){if(typeof J==="string"){this.addAttribute(j,J);return}this.addAttribute(j,J.value||"",J.nonce)}getAIPMessageBuffer(j,J){let $=j.findIndex((z)=>z[0]===Y.OP.OP_RETURN),q=[];if($===-1)q.push([Y.OP.OP_RETURN]),$=0;if(J)for(let z of J)q.push(j[$+z]);else for(let z of j)q.push(z);return q}formatAIPOutput(j,J,$){let q=[O("|"),O(E),O("BITCOIN_ECDSA"),O(J),O($,"base64")];return[...j,...q]}}var{toArray:o,toUTF8:Wj,toBase64:wj,toHex:Lj}=f.Utils,{electrumDecrypt:Yj,electrumEncrypt:Gj}=f.ECIES;class x extends T{key;idName;description;address;identityKey;constructor(j,J={}){super();this.key=j,this.address=this.getIdentitySigningKey().toPublicKey().toAddress(),this.idName="Member ID 1",this.description="",this.identityKey="",this.identityAttributes=this.parseAttributes(J)}getIdentitySigningKey(){return this.key.deriveChild(this.key.toPublicKey(),H)}getMemberKey(){return this.key.toPublicKey().toString()}getLegacyAddress(){return this.key.toPublicKey().toAddress()}signMessage(j,J){let $=this.getIdentitySigningKey();return this.signWithBSM(j,$)}signOpReturnWithAIP(j){let J=this.getAIPMessageBuffer(j),{address:$,signature:q}=this.signMessage(J.flat());return this.formatAIPOutput(J,$,q)}getPublicKey(){return this.getIdentitySigningKey().toPublicKey().toString()}import(j){this.idName=j.name,this.description=j.description,this.key=f.PrivateKey.fromWif(j.derivedPrivateKey),this.address=this.getIdentitySigningKey().toPublicKey().toAddress(),this.identityAttributes=j.identityAttributes||{},this.identityKey=j.identityKey}static fromMemberIdentity(j){let J=new x(f.PrivateKey.fromWif(j.derivedPrivateKey));return J.import(j),J}static fromBackup(j){let J=new x(f.PrivateKey.fromWif(j.wif)),$=JSON.parse(J.decrypt(j.id));return J.import($),J}export(){return{name:this.idName,description:this.description,derivedPrivateKey:this.key.toWif(),address:this.address,identityAttributes:this.getAttributes(),identityKey:this.identityKey}}getEncryptionKey(){return{privKey:this.key.deriveChild(this.key.toPublicKey(),F),pubKey:this.key.deriveChild(this.key.toPublicKey(),F).toPublicKey()}}getEncryptionPublicKey(){let{pubKey:j}=this.getEncryptionKey();return j.toString()}getEncryptionPrivateKeyWithSeed(j){let J=Lj(f.Hash.sha256(j,"utf8")),$=`${h}-${P}-${J}`;return this.key.deriveChild(this.key.toPublicKey(),$)}getEncryptionKeyWithSeed(j){let J=this.getEncryptionPrivateKeyWithSeed(j);return{privKey:J,pubKey:J.toPublicKey()}}getEncryptionPublicKeyWithSeed(j){return this.getEncryptionPrivateKeyWithSeed(j).toPublicKey().toString()}encryptWithSeed(j,J,$){let q=this.getEncryptionPrivateKeyWithSeed(J),z=q.toPublicKey(),Q=this.key.toPublicKey().constructor,W=$?Q.fromString($):z;return wj(Gj(o(j),W,q))}decryptWithSeed(j,J,$){let q=this.getEncryptionPrivateKeyWithSeed(J),z;if($)z=f.PublicKey.fromString($);return Wj(Yj(o(j,"base64"),q,z))}exportForBackup(j){let J=this.export(),$=this.encrypt(JSON.stringify(J));return{wif:this.key.toWif(),id:$,...j&&{label:j},createdAt:new Date().toISOString()}}}var{toArray:X,toHex:_,toBase58:Xj,toUTF8:u,toBase64:I}=w.Utils,{electrumDecrypt:d,electrumEncrypt:g}=w.ECIES;class V extends T{#J;#j;#q;#Q=S;#W="";#$;#Z;#z;#w;idName;description;rootAddress;identityKey;identityAttributes;getApiData;constructor(j,J={},$=""){super();if(j instanceof w.HD)if(this.#q=!1,$){let z=_(w.Hash.sha256($,"utf8")),Q=U.getSigningPathFromHex(z);this.#J=j.derive(Q)}else this.#J=j;else if(this.#q=!0,this.#j=j.rootPk,$){let z=_(w.Hash.sha256($,"utf8"));this.#j=this.#j.deriveChild(this.#j.toPublicKey(),z)}if(this.#w=$,this.idName="ID 1",this.description="",this.#$=`${R}/0/0/0`,this.#Z=`${R}/0/0/0`,this.#z=`${R}/0/0/1`,this.#q){if(!this.#j)throw Error("Master private key not initialized");let z=this.#j.deriveChild(this.#j.toPublicKey(),this.#$);this.rootAddress=z.toPublicKey().toAddress()}else{if(!this.#J)throw Error("HD private key not initialized");let z=this.#J.derive(this.#$);this.rootAddress=z.privKey.toPublicKey().toAddress()}this.identityKey=this.deriveIdentityKey(this.rootAddress);let q={...J};this.identityAttributes=this.parseAttributes(q),this.getApiData=N(this.#Q,this.#W)}set BAP_SERVER(j){this.#Q=j}get BAP_SERVER(){return this.#Q}set BAP_TOKEN(j){this.#W=j}get BAP_TOKEN(){return this.#W}deriveIdentityKey(j){let J=_(w.Hash.sha256(j,"utf8"));return Xj(w.Hash.ripemd160(J,"hex"))}parseAttributes(j){if(typeof j==="string")return this.parseStringUrns(j);for(let J in j)if(!j[J].value||!j[J].nonce)throw Error("Invalid identity attribute");return j||{}}parseStringUrns(j){let J={},$=j.replace(/^\s+/g,"").replace(/\r/gm,"").split(`
5
- `);for(let q of $){let Q=q.replace(/^\s+/g,"").replace(/\s+$/g,"").split(":");if(Q[0]==="urn"&&Q[1]==="bap"&&Q[2]==="id"&&Q[3]&&Q[4]&&Q[5])J[Q[3]]={value:Q[4],nonce:Q[5]}}return J}getIdentityKey(){return this.identityKey}set rootPath(j){if(this.#q){if(this.#$=j,!this.#j)throw Error("Master private key not initialized");let J=this.#j.deriveChild(this.#j.toPublicKey(),j);this.rootAddress=J.toPublicKey().toAddress(),this.#Z=j,this.#z=j}else{let J=j;if(j.split("/").length<5)J=`${R}${j}`;if(!this.validatePath(J))throw Error(`invalid signing path given ${J}`);if(this.#$=J,!this.#J)throw Error("HD private key not initialized");let $=this.#J.derive(J);this.rootAddress=$.pubKey.toAddress(),this.#Z=J,this.#z=J}this.identityKey=this.deriveIdentityKey(this.rootAddress)}get rootPath(){return this.#$}getRootPath(){return this.#$}set currentPath(j){if(this.#q)this.#Z=this.#z,this.#z=j;else{let J=j;if(j.split("/").length<5)J=`${R}${j}`;if(!this.validatePath(J))throw Error("invalid signing path given");this.#Z=this.#z,this.#z=J}}get currentPath(){return this.#z}get previousPath(){return this.#Z}get idSeed(){return this.#w}incrementPath(){this.currentPath=U.getNextPath(this.currentPath)}validatePath(j){if(j.match(/\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?/)){let J=j.split("/");if(J.length===7&&Number(J[1].replace("'",""))<=M&&Number(J[2].replace("'",""))<=M&&Number(J[3].replace("'",""))<=M&&Number(J[4].replace("'",""))<=M&&Number(J[5].replace("'",""))<=M&&Number(J[6].replace("'",""))<=M)return!0}return!1}getInitialIdTransaction(){return this.getIdTransaction(this.#$)}getIdTransaction(j=""){if(this.#z===this.#$)throw Error("Current path equals rootPath. ID was probably not initialized properly");let J=[X(k),X("ID"),X(this.identityKey),X(this.getCurrentAddress())];return this.signOpReturnWithAIP(J,j||this.#Z)}getPathDerivedKey(j){if(this.#q){if(!this.#j)throw Error("Master private key not initialized");return this.#j.deriveChild(this.#j.toPublicKey(),j)}if(!this.#J)throw Error("HD private key not initialized");return this.#J.derive(j).privKey}getIdentitySigningKeyForPath(j){let J=this.getPathDerivedKey(j);return J.deriveChild(J.toPublicKey(),H)}getMemberKey(j){let J=j||this.#z;return this.getPathDerivedKey(J).toPublicKey().toString()}getLegacyAddress(j){let J=j||this.#z;return this.getPathDerivedKey(J).toPublicKey().toAddress()}needsRotation(j){let J=j||this.rootAddress,$=this.getLegacyAddress(this.#$);return J===$}getLegacyRotationTransaction(){let j=this.getAddress(this.#$),J=[X(k),X("ID"),X(this.identityKey),X(j)],$=this.getAIPMessageBuffer(J),q=this.getPathDerivedKey(this.#$),{address:z,signature:Q}=this.signWithBSM($.flat(),q);return this.formatAIPOutput(J,z,Q)}getAddress(j){return this.getIdentitySigningKeyForPath(j).toPublicKey().toAddress()}getCurrentAddress(){return this.getAddress(this.#z)}getEncryptionKey(){if(this.#q){if(!this.#j)throw Error("Master private key not initialized");let $=this.#j.deriveChild(this.#j.toPublicKey(),this.#$),q=$.deriveChild($.toPublicKey(),F);return{privKey:q,pubKey:q.toPublicKey()}}if(!this.#J)throw Error("HD private key not initialized");let J=this.#J.derive(this.#$).derive(F).privKey;return{privKey:J,pubKey:J.toPublicKey()}}getEncryptionKeyType42(){if(this.#q)return this.getEncryptionKey();if(!this.#J)throw Error("HD private key not initialized");let j=this.#J.derive(this.#$),J=j.privKey.deriveChild(j.toPublic().pubKey,F);return{privKey:J,pubKey:J.toPublicKey()}}getEncryptionPublicKey(){let{pubKey:j}=this.getEncryptionKey();return j.toString()}getEncryptionPublicKeyWithSeed(j){return this.getEncryptionPrivateKeyWithSeed(j).toPublicKey().toString()}encrypt(j,J){let{privKey:$,pubKey:q}=this.getEncryptionKey(),z=J?w.PublicKey.fromString(J):q;return I(g(X(j),z,$))}decrypt(j,J){let{privKey:$}=this.getEncryptionKey(),q;if(J)q=w.PublicKey.fromString(J);return u(d(X(j,"base64"),$,q))}encryptWithSeed(j,J,$){let q=this.getEncryptionPrivateKeyWithSeed(J),z=q.toPublicKey(),Q=$?w.PublicKey.fromString($):z;return I(g(X(j),Q,q))}decryptWithSeed(j,J,$){let q=this.getEncryptionPrivateKeyWithSeed(J),z;if($)z=w.PublicKey.fromString($);return u(d(X(j,"base64"),q,z))}getEncryptionPrivateKeyWithSeed(j){let J=_(w.Hash.sha256(j,"utf8"));if(this.#q){if(!this.#j)throw Error("Master private key not initialized");let z=this.#j.deriveChild(this.#j.toPublicKey(),this.#$);return z.deriveChild(z.toPublicKey(),J)}if(!this.#J)throw Error("HD private key not initialized");let $=U.getSigningPathFromHex(J);return this.#J.derive(this.#$).derive($).privKey}getAttestation(j){let J=w.Hash.sha256(j,"utf8");return`bap:attest:${_(J)}:${this.getIdentityKey()}`}getAttestationHash(j){let J=this.getAttributeUrn(j);if(!J)return null;let $=this.getAttestation(J),q=w.Hash.sha256($,"utf8");return _(q)}signMessage(j,J){let $=J||this.#z,q=this.getIdentitySigningKeyForPath($);return this.signWithBSM(j,q)}signMessageWithSeed(j,J){let $=_(w.Hash.sha256(J,"utf8")),q;if(this.#q){if(!this.#j)throw Error("Master private key not initialized");let Q=this.#j.deriveChild(this.#j.toPublicKey(),this.#$);q=Q.deriveChild(Q.toPublicKey(),$)}else{if(!this.#J)throw Error("HD private key not initialized");let Q=U.getSigningPathFromHex($);q=this.#J.derive(this.#$).derive(Q).privKey}let z=q.deriveChild(q.toPublicKey(),H);return this.signWithBSM(X(j,"utf8"),z)}signOpReturnWithAIP(j,J=""){let $=this.getAIPMessageBuffer(j),{address:q,signature:z}=this.signMessage($.flat(),J);return this.formatAIPOutput(j,q,z)}async getIdSigningKeys(){let j=await this.getApiData("/signing-keys",{idKey:this.identityKey});return console.log("getIdSigningKeys",j),j}async getAttributeAttestations(j){let J=this.getAttestationHash(j),$=await this.getApiData("/attestation/get",{hash:J});return console.log("getAttestations",j,J,$),$}import(j){this.idName=j.name,this.description=j.description||"",this.identityKey=j.identityKey,this.#$=j.rootPath,this.rootAddress=j.rootAddress,this.#Z=j.previousPath,this.#z=j.currentPath,this.#w=("idSeed"in j?j.idSeed:"")||"",this.identityAttributes=this.parseAttributes(j.identityAttributes)}export(){return{name:this.idName,description:this.description,identityKey:this.identityKey,rootPath:this.#$,rootAddress:this.rootAddress,previousPath:this.#Z,currentPath:this.#z,idSeed:this.#w,identityAttributes:this.getAttributes(),lastIdPath:""}}exportMemberBackup(){let j=this.getPathDerivedKey(this.#z),J=this.getIdentitySigningKeyForPath(this.#z);return{name:this.idName,description:this.description,derivedPrivateKey:j.toWif(),address:J.toPublicKey().toAddress(),identityAttributes:this.getAttributes(),identityKey:this.identityKey}}newId(){this.incrementPath();let j=this.getPathDerivedKey(this.#z);return new x(j)}exportMember(){let j=this.exportMemberBackup(),J=this.getPathDerivedKey(this.#z),$=I(g(X(JSON.stringify(j)),J.toPublicKey()));return{wif:j.derivedPrivateKey,encryptedData:$}}}var{toArray:Z,toUTF8:B,toBase64:A,toHex:D}=s.Utils,{electrumEncrypt:n,electrumDecrypt:y}=L.ECIES;class i{#J;#j;#q;#Q={};#W=S;#$="";#Z="";#z=0;getApiData;constructor(j,J="",$=""){if(!j)throw Error("No key source given");if(typeof j==="string")this.#J=L.HD.fromString(j),this.#q=!1;else this.#j=L.PrivateKey.fromWif(j.rootPk),this.#q=!0;if(J)this.#$=J;if($)this.#W=$;this.getApiData=N(this.#W,this.#$)}get lastIdPath(){return this.#Z}getPublicKey(j=""){if(this.#q){if(!this.#j)throw Error("Master private key not initialized");if(j)return this.#j.deriveChild(this.#j.toPublicKey(),j).toPublicKey().toString();return this.#j.toPublicKey().toString()}if(!this.#J)throw Error("HD private key not initialized");if(j)return this.#J.derive(j).pubKey.toString();return this.#J.pubKey.toString()}getHdPublicKey(j=""){if(this.#q)throw Error("HD public keys are not available in Type 42 mode");if(!this.#J)throw Error("HD private key not initialized");if(j)return this.#J.derive(j).toPublic().toString();return this.#J.toPublic().toString()}set BAP_SERVER(j){this.#W=j;for(let J in this.#Q)this.#Q[J].BAP_SERVER=j}get BAP_SERVER(){return this.#W}set BAP_TOKEN(j){this.#$=j;for(let J in this.#Q)this.#Q[J].BAP_TOKEN=j}get BAP_TOKEN(){return this.#$}checkIdBelongs(j){let J;if(this.#q){if(!this.#j)throw Error("Master private key not initialized");J=this.#j.deriveChild(this.#j.toPublicKey(),j.rootPath).toPublicKey().toAddress()}else{if(!this.#J)throw Error("HD private key not initialized");J=this.#J.derive(j.rootPath).pubKey.toAddress()}if(J!==j.rootAddress)throw Error("ID does not belong to this private key");return!0}listIds(){return Object.keys(this.#Q)}newId(j,J,$={},q=""){let z,Q,W;if(typeof j==="object"||j===void 0||typeof j==="string"&&j.startsWith("/"))Q=typeof j==="string"?j:void 0,W=typeof j==="object"?j:typeof J==="object"?J:{},z="Default Identity";else z=j,Q=typeof J==="string"?J:void 0,W=typeof J==="object"?J:$;let G;if(Q)G=Q;else if(this.#q)G=`bap:${this.#z}`,this.#z++;else G=this.getNextValidPath();let C;if(this.#q){if(!this.#j)throw Error("Type 42 parameters not initialized");C=new V({rootPk:this.#j},W,q)}else{if(!this.#J)throw Error("HD private key not initialized");C=new V(this.#J,W,q)}if(C.BAP_SERVER=this.#W,C.BAP_TOKEN=this.#$,C.idName=z,C.rootPath=G,this.#q)C.currentPath=G;else C.currentPath=U.getNextPath(G);let l=C.getIdentityKey();return this.#Q[l]=C,this.#Z=G,this.#Q[l]}removeId(j){delete this.#Q[j]}getNextValidPath(){if(this.#Z)return U.getNextIdentityPath(this.#Z);return`/0'/${Object.keys(this.#Q).length}'/0'`}newIdWithCounter(j,J=`Identity ${j}`){if(!this.#q)throw Error("newIdWithCounter only works in Type 42 mode");let $=`bap:${j}`;return this.newId(J,$)}getId(j){return this.#Q[j]||null}setId(j){this.checkIdBelongs(j),this.#Q[j.getIdentityKey()]=j}importIds(j,J=!0){if(J&&typeof j==="string"){this.importEncryptedIds(j);return}let $=j;if(!$.lastIdPath)throw Error("ID cannot be imported as it is not complete");if(!$.ids)throw Error(`ID data is not in the correct format: ${j}`);let q=j.lastIdPath;for(let z of $.ids){if(!z.identityKey||!z.identityAttributes||!z.rootAddress)throw Error("ID cannot be imported as it is not complete");let Q;if(this.#q){if(!this.#j)throw Error("Type 42 parameters not initialized");Q=new V({rootPk:this.#j},{},z.idSeed)}else{if(!this.#J)throw Error("HD private key not initialized");Q=new V(this.#J,{},z.idSeed)}if(Q.BAP_SERVER=this.#W,Q.BAP_TOKEN=this.#$,Q.import(z),q==="")q=Q.currentPath;if(this.checkIdBelongs(Q),this.#Q[Q.getIdentityKey()]=Q,this.#q&&Q.rootPath.startsWith("bap:")){let W=Q.rootPath.split(":");if(W.length>=2){let G=Number.parseInt(W[1],10);if(!Number.isNaN(G))this.#z=Math.max(this.#z,G+1)}}}this.#Z=q}importEncryptedIds(j){let J=this.decrypt(j),$=JSON.parse(J);if(Array.isArray($)){console.log(`Importing old format:
6
- `,$),this.importOldIds($);return}if(typeof $!=="object")throw Error("decrypted, but found unrecognized identities format");this.importIds($,!1)}importOldIds(j){for(let J of j){let $;if(this.#q){if(!this.#j)throw Error("Type 42 parameters not initialized");$=new V({rootPk:this.#j},{},J.idSeed??"")}else{if(!this.#J)throw Error("HD private key not initialized");$=new V(this.#J,{},J.idSeed??"")}$.BAP_SERVER=this.#W,$.BAP_TOKEN=this.#$,$.import(J),this.checkIdBelongs($),this.#Q[$.getIdentityKey()]=$,this.#Z=$.currentPath}}exportIds(j,J=!0){let $={lastIdPath:this.#Z,ids:[]},q=j||Object.keys(this.#Q);for(let z of q){if(!this.#Q[z])throw Error(`Identity ${z} not found`);$.ids.push(this.#Q[z].export())}if(J)return this.encrypt(JSON.stringify($));return $}exportId(j,J=!0){let $={lastIdPath:this.#Z,ids:[]};if($.ids.push(this.#Q[j].export()),J)return this.encrypt(JSON.stringify($));return $}encrypt(j){if(this.#q){if(!this.#j)throw Error("Master private key not initialized");let $=this.#j.deriveChild(this.#j.toPublicKey(),F);return A(n(Z(j),$.toPublicKey(),null))}if(!this.#J)throw Error("HD private key not initialized");let J=this.#J.derive(F);return A(n(Z(j),J.pubKey,null))}decrypt(j){if(this.#q){if(!this.#j)throw Error("Master private key not initialized");let $=this.#j.deriveChild(this.#j.toPublicKey(),F);return B(y(Z(j,"base64"),$))}if(!this.#J)throw Error("HD private key not initialized");let J=this.#J.derive(F);return B(y(Z(j,"base64"),J.privKey))}signAttestationWithAIP(j,J,$=0,q=""){let z=this.getId(J);if(!z)throw Error("Could not find identity to attest with");let Q=this.getAttestationBuffer(j,$,q),{address:W,signature:G}=z.signMessage(Q);return this.createAttestationTransaction(j,$,W,G,q)}verifyAttestationWithAIP(j){if(!j.every((q)=>Array.isArray(q))||j[0][0]!==L.OP.OP_RETURN||D(j[1])!==p)throw Error("Not a valid BAP transaction");let J=D(j[7])==="44415441"?5:0,$={type:B(j[2]),hash:D(j[3]),sequence:B(j[4]),signingProtocol:B(j[7+J]),signingAddress:B(j[8+J]),signature:A(j[9+J])};if(J&&j[3]===j[8])$.data=D(j[9]);console.log({attestation:$});try{let q=[];for(let z=0;z<6+J;z++)q.push(j[z]);$.verified=this.verifySignature(q.flat(),$.signingAddress,$.signature)}catch{$.verified=!1}return $}createAttestationTransaction(j,J,$,q,z=""){let Q=[[L.OP.OP_RETURN],Z(k),Z("ATTEST"),Z(j),Z(`${J}`),Z("|")];if(z)Q.push(Z(k),Z("DATA"),Z(j),Z(z),Z("|"));return Q.push(Z(E),Z("BITCOIN_ECDSA"),Z($),Z(q,"base64")),console.log({elements:Q}),Q}getAttestationBuffer(j,J=0,$=""){let q=[[L.OP.OP_RETURN],Z(k),Z("ATTEST"),Z(j),Z(`${J}`),Z("|")];if($)q.push(Z(k),Z("DATA"),Z(j),Z($),Z("|"));return q.flat()}verifySignature(j,J,$){let q;if(Array.isArray(j))q=j;else if(Buffer.isBuffer(j))q=[...j];else q=Z(j,"utf8");let z=L.Signature.fromCompact($,"base64"),Q;for(let W=0;W<4;W++)try{if(Q=z.RecoverPublicKey(W,new L.BigNumber(L.BSM.magicHash(q))),L.BSM.verify(q,z,Q)&&Q.toAddress()===J)return!0}catch{}return!1}async verifyChallengeSignature(j,J,$,q){if(!this.verifySignature($,J,q))return!1;try{let Q=await this.getApiData("/attestation/valid",{idKey:j,address:J,challenge:$,signature:q});if(Q?.status==="success"&&Q?.result?.valid===!0)return!0;return!1}catch(Q){return console.error("API call failed:",Q),!1}}async isValidAttestationTransaction(j){if(this.verifyAttestationWithAIP(j))return this.getApiData("/attestation/valid",{tx:j});return!1}async getIdentityFromAddress(j){return this.getApiData("/identity/from-address",{address:j})}async getIdentity(j){return this.getApiData("/identity/get",{idKey:j})}async getAttestationsForHash(j){return this.getApiData("/attestations",{hash:j})}exportForBackup(j,J,$){let z={ids:this.exportIds(),...j&&{label:j},createdAt:new Date().toISOString()};if(this.#q){if(!this.#j)throw Error("Type 42 parameters not initialized");return{...z,rootPk:this.#j.toWif()}}if(!this.#J)throw Error("HD private key not initialized");return{...z,xprv:J||this.#J.toString(),mnemonic:$||""}}exportMemberForBackup(j,J){let $=this.#Q[j];if(!$)throw Error(`Identity ${j} not found`);let q=$.exportMember();return{wif:q.wif,id:q.encryptedData,...J&&{label:J},createdAt:new Date().toISOString()}}}})
7
-
8
- //# debugId=E05864240FBDCD8664756E2164756E21
package/src/README.md DELETED
@@ -1,583 +0,0 @@
1
- # BAP Library Documentation
2
-
3
- > Complete API reference for the bsv-bap JavaScript/TypeScript library
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install bsv-bap
9
- ```
10
-
11
- ```bash
12
- yarn add bsv-bap
13
- ```
14
-
15
- ```bash
16
- bun add bsv-bap
17
- ```
18
-
19
- ## Core Classes
20
-
21
- ### BAP
22
-
23
- The main class for managing Bitcoin Attestation Protocol identities.
24
-
25
- #### Constructor
26
-
27
- ```typescript
28
- // BIP32 mode (legacy)
29
- const bap = new BAP(xprvKey: string);
30
-
31
- // Type 42 mode (recommended)
32
- const bap = new BAP({
33
- rootPk: string // WIF format private key
34
- });
35
- ```
36
-
37
- #### Methods
38
-
39
- ##### Identity Management
40
-
41
- ```typescript
42
- // Create a new identity (new signature - Type 42 optimized)
43
- newId(idName?: string, customPath?: string, identityAttributes?: IdentityAttributes, idSeed?: string): MasterID
44
-
45
- // Create identity with specific counter (useful for discovery)
46
- newIdWithCounter(counter: number, idName?: string): MasterID
47
-
48
- // Get an identity by key
49
- getId(idKey: string): MasterID | null
50
-
51
- // List all identity keys
52
- listIds(): string[]
53
-
54
- // Remove an identity
55
- removeId(idKey: string): void
56
-
57
- // Check if identity belongs to this BAP instance
58
- checkIdBelongs(id: MasterID): boolean
59
- ```
60
-
61
- ##### Import/Export
62
-
63
- ```typescript
64
- // Export identities (encrypted by default)
65
- exportIds(idKeys?: string[], encrypted?: boolean): string | Identities
66
-
67
- // Export specific identity
68
- exportId(idKey: string, encrypted?: boolean): string | Identities
69
-
70
- // Import identities
71
- importIds(identities: string | Identities, encrypted?: boolean): void
72
-
73
- // Bitcoin-backup compatible export
74
- exportForBackup(label?: string, xprv?: string, mnemonic?: string): BapMasterBackup
75
-
76
- // Export member backup
77
- exportMemberForBackup(idKey: string, label?: string): BapMemberBackup
78
- ```
79
-
80
- ##### Cryptographic Operations
81
-
82
- ```typescript
83
- // Create attestation transaction
84
- signAttestationWithAIP(
85
- attestationHash: string,
86
- identityKey: string,
87
- counter?: number,
88
- dataString?: string
89
- ): number[][]
90
-
91
- // Verify attestation
92
- verifyAttestationWithAIP(txData: number[][]): AttestationResult
93
-
94
- // Verify signature
95
- verifySignature(
96
- message: string | number[],
97
- address: string,
98
- signature: string
99
- ): boolean
100
-
101
- // Verify challenge signature (with API validation)
102
- async verifyChallengeSignature(
103
- idKey: string,
104
- address: string,
105
- challenge: string,
106
- signature: string
107
- ): Promise<boolean>
108
- ```
109
-
110
- ##### Encryption
111
-
112
- ```typescript
113
- // Encrypt data using BAP master key
114
- encrypt(data: string): string
115
-
116
- // Decrypt data using BAP master key
117
- decrypt(encryptedData: string): string
118
- ```
119
-
120
- ##### Configuration
121
-
122
- ```typescript
123
- // Set/get API server
124
- BAP_SERVER: string // Default: https://api.sigmaidentity.com/v1
125
-
126
- // Set/get API token
127
- BAP_TOKEN: string
128
- ```
129
-
130
- ### MasterID
131
-
132
- Represents an individual identity with HD key derivation support.
133
-
134
- #### Properties
135
-
136
- ```typescript
137
- idName: string // Identity name
138
- description: string // Identity description
139
- identityKey: string // Unique identity key
140
- rootAddress: string // Root Bitcoin address
141
- identityAttributes: IdentityAttributes
142
- ```
143
-
144
- #### Methods
145
-
146
- ##### Attribute Management
147
-
148
- ```typescript
149
- // Set attribute
150
- setAttribute(name: string, value: string | IdentityAttribute): void
151
-
152
- // Get attribute
153
- getAttribute(name: string): IdentityAttribute | null
154
-
155
- // Get all attributes
156
- getAttributes(): IdentityAttributes
157
-
158
- // Remove attribute
159
- unsetAttribute(name: string): void
160
-
161
- // Get attribute URN
162
- getAttributeUrn(name: string): string | null
163
- ```
164
-
165
- ##### Key Management
166
-
167
- ```typescript
168
- // Get current signing address
169
- getCurrentAddress(): string
170
-
171
- // Get address for specific path
172
- getAddress(path: string): string
173
-
174
- // Increment to next path
175
- incrementPath(): void
176
-
177
- // Get encryption public key
178
- getEncryptionPublicKey(): string
179
- ```
180
-
181
- ##### Signing
182
-
183
- ```typescript
184
- // Sign message
185
- signMessage(
186
- message: number[],
187
- signingPath?: string
188
- ): { address: string; signature: string }
189
-
190
- // Sign message with seed
191
- signMessageWithSeed(
192
- message: string,
193
- seed: string
194
- ): { address: string; signature: string }
195
-
196
- // Sign OP_RETURN with AIP
197
- signOpReturnWithAIP(
198
- opReturn: number[][],
199
- signingPath?: string
200
- ): number[][]
201
- ```
202
-
203
- ##### Encryption
204
-
205
- ```typescript
206
- // Encrypt data
207
- encrypt(data: string, counterPartyPublicKey?: string): string
208
-
209
- // Decrypt data
210
- decrypt(ciphertext: string, counterPartyPublicKey?: string): string
211
-
212
- // Encrypt with seed
213
- encryptWithSeed(
214
- data: string,
215
- seed: string,
216
- counterPartyPublicKey?: string
217
- ): string
218
-
219
- // Decrypt with seed
220
- decryptWithSeed(
221
- ciphertext: string,
222
- seed: string,
223
- counterPartyPublicKey?: string
224
- ): string
225
- ```
226
-
227
- ##### Attestations
228
-
229
- ```typescript
230
- // Get attestation hash for attribute
231
- getAttestationHash(attribute: string): string | null
232
-
233
- // Get attestation URN
234
- getAttestation(urn: string): string
235
-
236
- // Get all attestations for attribute (API call)
237
- async getAttributeAttestations(attribute: string): Promise<GetAttestationResponse>
238
- ```
239
-
240
- ##### Transactions
241
-
242
- ```typescript
243
- // Get initial ID transaction
244
- getInitialIdTransaction(): number[][]
245
-
246
- // Get ID transaction for rotation
247
- getIdTransaction(previousPath?: string): number[][]
248
- ```
249
-
250
- ### MemberID
251
-
252
- Represents a standalone member identity (non-HD).
253
-
254
- #### Constructor
255
-
256
- ```typescript
257
- const member = new MemberID(privateKey: PrivateKey, attributes?: IdentityAttributes);
258
- ```
259
-
260
- #### Methods
261
-
262
- ##### Core Operations
263
-
264
- ```typescript
265
- // Get public key
266
- getPublicKey(): string
267
-
268
- // Sign message
269
- signMessage(message: number[]): { address: string; signature: string }
270
-
271
- // Sign OP_RETURN with AIP
272
- signOpReturnWithAIP(opReturn: number[][]): number[][]
273
- ```
274
-
275
- ##### Import/Export
276
-
277
- ```typescript
278
- // Export member data
279
- export(): MemberIdentity
280
-
281
- // Import member data
282
- import(memberData: MemberIdentity): void
283
-
284
- // Export for backup
285
- exportForBackup(label?: string): BapMemberBackup
286
-
287
- // Create from backup
288
- static fromBackup(backup: BapMemberBackup): MemberID
289
-
290
- // Create from member identity
291
- static fromMemberIdentity(identity: MemberIdentity): MemberID
292
- ```
293
-
294
- ## Type System
295
-
296
- ### Core Types
297
-
298
- ```typescript
299
- interface IdentityAttribute {
300
- value: string;
301
- nonce: string;
302
- }
303
-
304
- interface IdentityAttributes {
305
- [key: string]: IdentityAttribute;
306
- }
307
-
308
- interface Identity {
309
- name: string;
310
- description: string;
311
- identityKey: string;
312
- rootPath: string;
313
- rootAddress: string;
314
- previousPath: string;
315
- currentPath: string;
316
- idSeed: string;
317
- identityAttributes: IdentityAttributes;
318
- lastIdPath: string;
319
- }
320
-
321
- interface MemberIdentity {
322
- name: string;
323
- description: string;
324
- derivedPrivateKey: string;
325
- address: string;
326
- identityAttributes: IdentityAttributes;
327
- identityKey: string;
328
- }
329
- ```
330
-
331
- ### Backup Types
332
-
333
- ```typescript
334
- // Type 42 format
335
- interface BapMasterBackup {
336
- ids: string; // Encrypted identity data
337
- rootPk: string; // WIF format private key
338
- label?: string; // Optional label
339
- createdAt: string; // ISO timestamp
340
- }
341
-
342
- // Legacy BIP32 format
343
- interface BapMasterBackup {
344
- ids: string; // Encrypted identity data
345
- xprv: string; // Extended private key
346
- mnemonic: string; // BIP39 mnemonic
347
- label?: string; // Optional label
348
- createdAt: string; // ISO timestamp
349
- }
350
-
351
- interface BapMemberBackup {
352
- wif: string; // WIF private key
353
- id: string; // Encrypted member data
354
- label?: string; // Optional label
355
- createdAt: string; // ISO timestamp
356
- }
357
- ```
358
-
359
- ### API Types
360
-
361
- ```typescript
362
- interface AttestationResult {
363
- type: string;
364
- hash: string;
365
- sequence: string;
366
- signingProtocol: string;
367
- signingAddress: string;
368
- signature: string;
369
- data?: string;
370
- verified?: boolean;
371
- }
372
- ```
373
-
374
- ## Key Derivation
375
-
376
- ### BIP32 Mode (Legacy)
377
-
378
- Uses hierarchical deterministic key derivation:
379
-
380
- ```
381
- m/424150'/0'/0'/[identity]/[key]/[index]
382
- ```
383
-
384
- ### Type 42 Mode (Recommended)
385
-
386
- Uses simple counter-based derivation with meaningful names:
387
-
388
- ```typescript
389
- // Invoice numbers: "bap:0", "bap:1", "bap:2", etc.
390
- const work = bap.newId("Work Identity"); // Uses bap:0
391
- const personal = bap.newId("Personal"); // Uses bap:1
392
-
393
- // Derivation uses counter as invoice number
394
- derivedKey = masterKey.deriveChild(
395
- masterKey.toPublicKey(),
396
- "bap:0" // Simple counter format
397
- );
398
-
399
- // Names are stored separately for UX
400
- identity.idName = "Work Identity"; // Human-readable name
401
- identity.rootPath = "bap:0"; // Cryptographic derivation path
402
- ```
403
-
404
- **Discovery**: Sequential counters enable systematic identity recovery:
405
-
406
- ```typescript
407
- // Find all identities by checking counters
408
- for (let i = 0; i < 100; i++) {
409
- const identity = bap.newIdWithCounter(i);
410
- if (await blockchainHasActivity(identity.getIdentityKey())) {
411
- console.log(`Found identity: ${identity.idName}`);
412
- }
413
- }
414
- ```
415
-
416
- ### Encryption Keys
417
-
418
- Each identity has a unique encryption key:
419
-
420
- ```
421
- BIP32: rootPath → m/424150'/2147483647'/2147483647'
422
- Type 42: rootKey → deriveChild(rootPk.pubKey, path)
423
- ```
424
-
425
- ## Usage Examples
426
-
427
- ### Complete Identity Creation Flow
428
-
429
- ```typescript
430
- import { BAP } from 'bsv-bap';
431
- import { PrivateKey } from '@bsv/sdk';
432
-
433
- // Create BAP instance (Type 42)
434
- const rootKey = PrivateKey.fromRandom();
435
- const bap = new BAP({
436
- rootPk: rootKey.toWif()
437
- });
438
-
439
- // Create identity
440
- const identity = bap.newId();
441
- identity.idName = "Professional Identity";
442
- identity.description = "My verified professional identity";
443
-
444
- // Set attributes
445
- identity.setAttribute('name', 'John Smith');
446
- identity.setAttribute('title', 'Software Engineer');
447
- identity.setAttribute('company', 'Bitcoin Corp');
448
-
449
- // Get attestation for verification
450
- const nameHash = identity.getAttestationHash('name');
451
- console.log('Name attestation hash:', nameHash);
452
-
453
- // Create ID transaction
454
- const idTx = identity.getInitialIdTransaction();
455
- // Broadcast idTx to Bitcoin network...
456
-
457
- // Export for backup
458
- const backup = bap.exportForBackup('Main Identity');
459
- // Save backup securely...
460
- ```
461
-
462
- ### Attestation Workflow
463
-
464
- ```typescript
465
- // Company attests to employee identity
466
- const companyBap = new BAP(companyXprv);
467
- const companyId = companyBap.getId(companyIdKey);
468
-
469
- // Create attestation
470
- const attestation = companyBap.signAttestationWithAIP(
471
- employeeNameHash,
472
- companyIdKey,
473
- 0, // sequence
474
- JSON.stringify({
475
- verified: true,
476
- role: 'Senior Engineer',
477
- date: new Date().toISOString()
478
- })
479
- );
480
-
481
- // Verify attestation
482
- const result = await companyBap.verifyAttestationWithAIP(attestation);
483
- console.log('Attestation valid:', result.verified);
484
- ```
485
-
486
- ### Encrypted Communication
487
-
488
- ```typescript
489
- // Alice encrypts message for Bob
490
- const alice = bap.getId(aliceIdKey);
491
- const bobPublicKey = await getBobsPublicKey();
492
-
493
- const encrypted = alice.encrypt(
494
- 'Secret message for Bob',
495
- bobPublicKey
496
- );
497
-
498
- // Bob decrypts message
499
- const bob = bobBap.getId(bobIdKey);
500
- const alicePublicKey = await getAlicesPublicKey();
501
-
502
- const decrypted = bob.decrypt(
503
- encrypted,
504
- alicePublicKey
505
- );
506
- ```
507
-
508
- ### Member Identity
509
-
510
- ```typescript
511
- // Create standalone member identity
512
- const memberKey = PrivateKey.fromRandom();
513
- const member = new MemberID(memberKey);
514
-
515
- member.idName = "Forum Member";
516
- member.setAttribute('username', 'satoshi2024');
517
-
518
- // Sign a message
519
- const { address, signature } = member.signMessage(
520
- Buffer.from('I approve this message')
521
- );
522
-
523
- // Export for sharing
524
- const memberBackup = member.exportForBackup('Forum Identity');
525
- ```
526
-
527
- ## Migration Guide
528
-
529
- ### From BIP32 to Type 42
530
-
531
- ```typescript
532
- // Export from BIP32
533
- const oldBap = new BAP(xprv);
534
- const backup = oldBap.exportForBackup();
535
-
536
- // Extract root key
537
- const hdKey = HD.fromString(xprv);
538
- const rootWif = hdKey.privKey.toWif();
539
-
540
- // Create Type 42 instance
541
- const newBap = new BAP({
542
- rootPk: rootWif
543
- });
544
-
545
- // Create new identity and link to old
546
- const newId = newBap.newId();
547
- // Create ID transaction pointing from last old address to new...
548
- ```
549
-
550
- See [Type 42 Migration Guide](../docs/TYPE42_MIGRATION.md) for complete details.
551
-
552
- ## Best Practices
553
-
554
- 1. **Key Security**: Never expose private keys. Use encryption for all exports.
555
- 2. **Attribute Nonces**: Always use random nonces for attributes to prevent dictionary attacks.
556
- 3. **Path Management**: Let the library manage paths unless you have specific requirements.
557
- 4. **Backup Regularly**: Export and securely store identity backups.
558
- 5. **Verify Attestations**: Always verify attestations before trusting identity claims.
559
-
560
- ## Error Handling
561
-
562
- ```typescript
563
- try {
564
- const identity = bap.getId(idKey);
565
- if (!identity) {
566
- throw new Error('Identity not found');
567
- }
568
-
569
- const encrypted = identity.encrypt(data);
570
- } catch (error) {
571
- if (error.message.includes('not initialized')) {
572
- // Handle key initialization errors
573
- } else if (error.message.includes('not found')) {
574
- // Handle missing identity
575
- }
576
- }
577
- ```
578
-
579
- ## API Reference
580
-
581
- For protocol-level documentation, see [PROTOCOL.md](../PROTOCOL.md).
582
-
583
- For blockchain API endpoints, see the [BAP API Documentation](https://api.sigmaidentity.com/docs).