1: <?php declare( strict_types = 1 );
2:
3: namespace Waves\Transactions;
4:
5: use Exception;
6: use Waves\Account\PrivateKey;
7: use Waves\Common\Base58String;
8: use Waves\Account\PublicKey;
9: use Waves\Common\Base64String;
10: use Waves\Common\ExceptionCode;
11: use Waves\Common\Json;
12: use Waves\Model\ChainId;
13:
14: use Waves\Transactions\IssueTransaction as CurrentTransaction;
15:
16: class IssueTransaction extends Transaction
17: {
18: const TYPE = 3;
19: const LATEST_VERSION = 3;
20: const MIN_FEE = 100_000_000;
21: const NFT_MIN_FEE = 100_000;
22:
23: private string $name;
24: private string $description;
25: private int $quantity;
26: private int $decimals;
27: private bool $isReissuable;
28: private Base64String $script;
29:
30: static function build( PublicKey $sender, string $name, string $description, int $quantity, int $decimals,
31: bool $isReissuable, Base64String $script = null ): CurrentTransaction
32: {
33: $minFee = ( $quantity === 1 && $decimals === 0 && $isReissuable === false ) ? CurrentTransaction::NFT_MIN_FEE : CurrentTransaction::MIN_FEE;
34:
35: $tx = new CurrentTransaction;
36: $tx->setBase( $sender, CurrentTransaction::TYPE, CurrentTransaction::LATEST_VERSION, $minFee );
37:
38: // ISSUE TRANSACTION
39: {
40: $tx->setName( $name );
41: $tx->setDescription( $description );
42: $tx->setQuantity( $quantity );
43: $tx->setDecimals( $decimals );
44: $tx->setIsReissuable( $isReissuable );
45: $tx->setScript( $script );
46: }
47:
48: return $tx;
49: }
50:
51: function getUnsigned(): CurrentTransaction
52: {
53: // VERSION
54: if( $this->version() !== CurrentTransaction::LATEST_VERSION )
55: throw new Exception( __FUNCTION__ . ' unexpected version = ' . $this->version(), ExceptionCode::UNEXPECTED );
56:
57: // BASE
58: $pb_Transaction = $this->getProtobufTransactionBase();
59:
60: // ISSUE TRANSACTION
61: {
62: $pb_TransactionData = new \Waves\Protobuf\IssueTransactionData;
63: // NAME
64: {
65: $pb_TransactionData->setName( $this->name() );
66: }
67: // DESCRIPTION
68: {
69: $pb_TransactionData->setDescription( $this->description() );
70: }
71: // QUANTITY
72: {
73: $pb_TransactionData->setAmount( $this->quantity() );
74: }
75: // DECIMALS
76: {
77: $pb_TransactionData->setDecimals( $this->decimals() );
78: }
79: // REISSUABLE
80: {
81: $pb_TransactionData->setReissuable( $this->isReissuable() );
82: }
83: // SCRIPT
84: {
85: $pb_TransactionData->setScript( $this->script()->bytes() );
86: }
87: }
88:
89: // ISSUE TRANSACTION
90: $this->setBodyBytes( $pb_Transaction->setIssue( $pb_TransactionData )->serializeToString() );
91: return $this;
92: }
93:
94: function name(): string
95: {
96: if( !isset( $this->name ) )
97: $this->name = $this->json->get( 'name' )->asString();
98: return $this->name;
99: }
100:
101: function setName( string $name ): CurrentTransaction
102: {
103: $this->name = $name;
104: $this->json->put( 'name', $name );
105: return $this;
106: }
107:
108: function description(): string
109: {
110: if( !isset( $this->description ) )
111: $this->description = $this->json->get( 'description' )->asString();
112: return $this->description;
113: }
114:
115: function setDescription( string $description ): CurrentTransaction
116: {
117: $this->description = $description;
118: $this->json->put( 'description', $description );
119: return $this;
120: }
121:
122: function quantity(): int
123: {
124: if( !isset( $this->quantity ) )
125: $this->quantity = $this->json->get( 'quantity' )->asInt();
126: return $this->quantity;
127: }
128:
129: function setQuantity( int $quantity ): CurrentTransaction
130: {
131: $this->quantity = $quantity;
132: $this->json->put( 'quantity', $quantity );
133: return $this;
134: }
135:
136: function decimals(): int
137: {
138: if( !isset( $this->decimals ) )
139: $this->decimals = $this->json->get( 'decimals' )->asInt();
140: return $this->decimals;
141: }
142:
143: function setDecimals( int $decimals ): CurrentTransaction
144: {
145: $this->decimals = $decimals;
146: $this->json->put( 'decimals', $decimals );
147: return $this;
148: }
149:
150: function isReissuable(): bool
151: {
152: if( !isset( $this->isReissuable ) )
153: $this->isReissuable = $this->json->get( 'reissuable' )->asBoolean();
154: return $this->isReissuable;
155: }
156:
157: function setIsReissuable( bool $isReissuable ): CurrentTransaction
158: {
159: $this->isReissuable = $isReissuable;
160: $this->json->put( 'reissuable', $isReissuable );
161: return $this;
162: }
163:
164: function script(): Base64String
165: {
166: if( !isset( $this->script ) )
167: $this->script = $this->json->exists( 'script' ) ? $this->json->get( 'script' )->asBase64String() : Base64String::emptyString();
168: return $this->script;
169: }
170:
171: function setScript( Base64String $script = null ): CurrentTransaction
172: {
173: $script = $script ?? Base64String::emptyString();
174: $this->script = $script;
175: $this->json->put( 'script', $script->toJsonValue() );
176: return $this;
177: }
178:
179: // COMMON
180:
181: function __construct( Json $json = null )
182: {
183: parent::__construct( $json );
184: }
185:
186: function addProof( PrivateKey $privateKey, int $index = null ): CurrentTransaction
187: {
188: $proof = (new \deemru\WavesKit)->sign( $this->bodyBytes(), $privateKey->bytes() );
189: if( $proof === false )
190: throw new Exception( __FUNCTION__ . ' unexpected sign() error', ExceptionCode::UNEXPECTED );
191: $proof = Base58String::fromBytes( $proof )->encoded();
192:
193: $proofs = $this->proofs();
194: if( !isset( $index ) )
195: $proofs[] = $proof;
196: else
197: $proofs[$index] = $proof;
198: return $this->setProofs( $proofs );
199: }
200:
201: /**
202: * @return CurrentTransaction
203: */
204: function setType( int $type )
205: {
206: parent::setType( $type );
207: return $this;
208: }
209:
210: /**
211: * @return CurrentTransaction
212: */
213: function setSender( PublicKey $sender )
214: {
215: parent::setSender( $sender );
216: return $this;
217: }
218:
219: /**
220: * @return CurrentTransaction
221: */
222: function setVersion( int $version )
223: {
224: parent::setVersion( $version );
225: return $this;
226: }
227:
228: /**
229: * @return CurrentTransaction
230: */
231: function setFee( Amount $fee )
232: {
233: parent::setFee( $fee );
234: return $this;
235: }
236:
237: /**
238: * @return CurrentTransaction
239: */
240: function setChainId( ChainId $chainId = null )
241: {
242: parent::setChainId( $chainId );
243: return $this;
244: }
245:
246: /**
247: * @return CurrentTransaction
248: */
249: function setTimestamp( int $timestamp = null )
250: {
251: parent::setTimestamp( $timestamp );
252: return $this;
253: }
254:
255: /**
256: * @param array<int, string> $proofs
257: * @return CurrentTransaction
258: */
259: function setProofs( array $proofs = null )
260: {
261: parent::setProofs( $proofs );
262: return $this;
263: }
264:
265: function bodyBytes(): string
266: {
267: if( !isset( $this->bodyBytes ) )
268: $this->getUnsigned();
269: return parent::bodyBytes();
270: }
271: }
272: