diff --git a/cmd/runestonecli/config.go b/cmd/runestonecli/config.go index 0746b55..58ccd27 100644 --- a/cmd/runestonecli/config.go +++ b/cmd/runestonecli/config.go @@ -3,6 +3,8 @@ package main import ( "encoding/hex" "errors" + "net/http" + "os" "unicode/utf8" "github.com/btcsuite/btcd/btcec/v2" @@ -22,6 +24,7 @@ type Config struct { RpcUrl string Etching *struct { Rune string + Logo string Symbol *string Premine *uint64 Amount *uint64 @@ -184,3 +187,42 @@ func (c Config) GetPrivateKeyAddr() (*btcec.PrivateKey, string, error) { address := addr.EncodeAddress() return privKey, address, nil } +func (c Config) GetRuneLogo() (mime string, data []byte) { + if c.Etching != nil && c.Etching.Logo != "" { + mime, err := getContentType(c.Etching.Logo) + if err != nil { + return "", nil + } + data, err := getFileBytes(c.Etching.Logo) + if err != nil { + return "", nil + } + return mime, data + + } + return "", nil +} + +func getContentType(filePath string) (string, error) { + file, err := os.Open(filePath) + if err != nil { + return "", err + } + defer file.Close() + + buffer := make([]byte, 512) + _, err = file.Read(buffer) + if err != nil { + return "", err + } + + contentType := http.DetectContentType(buffer) + return contentType, nil +} +func getFileBytes(filePath string) ([]byte, error) { + fileBytes, err := os.ReadFile(filePath) + if err != nil { + return nil, err + } + return fileBytes, nil +} diff --git a/cmd/runestonecli/config.yaml b/cmd/runestonecli/config.yaml index 8f7cfe9..c066425 100644 --- a/cmd/runestonecli/config.yaml +++ b/cmd/runestonecli/config.yaml @@ -4,7 +4,8 @@ RpcUrl: "https://mempool.space/testnet/api" #https://mempool.space/api https://m FeePerByte: 10 UtxoAmount: 666 Etching: - Rune: "GOOD.LUCK.COIN" + Rune: "BXE.LAB.COIN" + Logo: "./logo.png" Symbol: "🪙" Premine: 1000000 Amount: 1000 diff --git a/cmd/runestonecli/logo.png b/cmd/runestonecli/logo.png new file mode 100644 index 0000000..2b25f6c Binary files /dev/null and b/cmd/runestonecli/logo.png differ diff --git a/cmd/runestonecli/main.go b/cmd/runestonecli/main.go index 7354de3..03b809e 100644 --- a/cmd/runestonecli/main.go +++ b/cmd/runestonecli/main.go @@ -86,8 +86,13 @@ func BuildEtchingTxs() { btcConnector := NewMempoolConnector(config) prvKey, address, _ := config.GetPrivateKeyAddr() utxos, err := btcConnector.GetUtxos(address) - - cTx, rTx, err := BuildRuneEtchingTxs(prvKey, utxos, data, commitment, config.GetFeePerByte(), config.GetUtxoAmount(), config.GetNetwork(), address) + var cTx, rTx []byte + mime, logoData := config.GetRuneLogo() + if len(mime) == 0 { + cTx, rTx, err = BuildRuneEtchingTxs(prvKey, utxos, data, commitment, config.GetFeePerByte(), config.GetUtxoAmount(), config.GetNetwork(), address) + } else { + cTx, rTx, err = BuildInscriptionTxs(prvKey, utxos, mime, logoData, config.GetFeePerByte(), config.GetUtxoAmount(), config.GetNetwork(), commitment, data) + } if err != nil { p.Println("BuildRuneEtchingTxs error:", err.Error()) return diff --git a/cmd/runestonecli/ordi-tx.go b/cmd/runestonecli/ordi-tx.go index c3aaab0..5beb9f8 100644 --- a/cmd/runestonecli/ordi-tx.go +++ b/cmd/runestonecli/ordi-tx.go @@ -24,7 +24,7 @@ const ( MaxStandardTxWeight = blockchain.MaxBlockWeight / 10 ) -func BuildInscriptionTxs(privateKey *btcec.PrivateKey, utxo []*Utxo, mime string, content []byte, feeRate int64, revealValue int64, net *chaincfg.Params) ([]byte, []byte, error) { +func BuildInscriptionTxs(privateKey *btcec.PrivateKey, utxo []*Utxo, mime string, content []byte, feeRate int64, revealValue int64, net *chaincfg.Params, inscriptionAddData []byte, opReturnData []byte) ([]byte, []byte, error) { //build 2 tx, 1 transfer BTC to taproot address, 2 inscription transfer taproot address to another address pubKey := privateKey.PubKey() receiver, err := getP2TRAddress(pubKey, net) @@ -32,7 +32,7 @@ func BuildInscriptionTxs(privateKey *btcec.PrivateKey, utxo []*Utxo, mime string return nil, nil, err } // 1. build inscription script - inscriptionScript, err := CreateInscriptionScript(pubKey, mime, content) + inscriptionScript, err := CreateInscriptionScript(pubKey, mime, content, inscriptionAddData) if err != nil { return nil, nil, err } @@ -42,7 +42,7 @@ func BuildInscriptionTxs(privateKey *btcec.PrivateKey, utxo []*Utxo, mime string } inscriptionPkScript, _ := txscript.PayToAddrScript(inscriptionAddress) // 2. build reveal tx - revealTx, totalPrevOutput, err := buildEmptyRevealTx(receiver, inscriptionScript, revealValue, feeRate, nil) + revealTx, totalPrevOutput, err := buildEmptyRevealTx(receiver, inscriptionScript, revealValue, feeRate, opReturnData) if err != nil { return nil, nil, err } diff --git a/cmd/runestonecli/tapescript.go b/cmd/runestonecli/tapescript.go index 9a3f419..77cc888 100644 --- a/cmd/runestonecli/tapescript.go +++ b/cmd/runestonecli/tapescript.go @@ -13,7 +13,7 @@ import ( "github.com/btcsuite/btcd/wire" ) -func CreateInscriptionScript(pk *btcec.PublicKey, contentType string, fileBytes []byte) ([]byte, error) { +func CreateInscriptionScript(pk *btcec.PublicKey, contentType string, fileBytes []byte, inscriptionAddData []byte) ([]byte, error) { builder := txscript.NewScriptBuilder() //push pubkey pk32 := schnorr.SerializePubKey(pk) @@ -21,6 +21,10 @@ func CreateInscriptionScript(pk *btcec.PublicKey, contentType string, fileBytes builder.AddData(pk32) builder.AddOp(txscript.OP_CHECKSIG) //Ordinals script + if len(inscriptionAddData) > 0 { + builder.AddData(inscriptionAddData) + builder.AddOp(txscript.OP_DROP) + } builder.AddOp(txscript.OP_FALSE) builder.AddOp(txscript.OP_IF) builder.AddData([]byte("ord"))