# Class BSV::Script::PushDropTemplate <a id="class-BSV-Script-PushDropTemplate"></a>

**Inherits:** `Object`

Wallet-integrated PushDrop template for any protocol.

Generalises the pattern used by {BSV::Overlay::AdminTokenTemplate} —derives a
locking key from the wallet, optionally signs the data fields, and wraps
everything in a PushDrop script backed by a P2PKH condition.

## Note: P2PKH vs P2PK

This template uses P2PKH as the underlying spending condition. The
{BSV::Overlay::AdminTokenTemplate} uses P2PK (matching the TS/Go SDKs' overlay
admin token convention). The two lock types are not interchangeable — tokens
locked by one cannot be unlocked by the other.

PushDrop scripts embed arbitrary token data inline in a spendable output:

    <field0> <field1> ... <fieldN> [OP_2DROP...] [OP_DROP?]
    OP_DUP OP_HASH160 <hash160(derived_pubkey)> OP_EQUALVERIFY OP_CHECKSIG

When +include_signature: true+ (the default), an ECDSA signature over the
concatenation of all fields is appended as a final field. This authenticates
the token at creation time using the same derived key.

## Security note: +counterparty: 'anyone'+ tokens

When `counterparty` is +'anyone'+, the locking key is derived from the
secp256k1 generator point G (PrivateKey(1)). This is a publicly known scalar,
meaning:

1.  The output is **publicly spendable** — any party can sign with
    PrivateKey(1) and spend the token. This is by design for overlay tokens
    where public revocability is desired.
2.  The field signature (+include_signature: true+) provides **no authenticity
    guarantee** — anyone can produce a valid signature with the known key.
    Rely on higher-level mechanisms (e.g. certificate keyrings from
    `prove_certificate`) for field-level integrity.

**@example Lock a token**
```ruby
wallet   = BSV::Wallet::Client.new(private_key, storage: BSV::Wallet::Store::Memory.new)
template = BSV::Script::PushDropTemplate.new(wallet:)
script   = template.lock(
  fields:       ['hello'.b, 'world'.b],
  protocol_id:  [1, 'my-protocol'],
  key_id:       '1',
  counterparty: 'self'
)
script.pushdrop? #=> true
```

**@example Unlock a token**
```ruby
unlocker = template.unlock(
  protocol_id:  [1, 'my-protocol'],
  key_id:       '1',
  counterparty: 'self'
)
input.unlocking_script_template = unlocker
```

## Constants
### `GENERATOR_PUBKEY_HEX` <a id="constant-GENERATOR_PUBKEY_HEX"></a> <a id="GENERATOR_PUBKEY_HEX-constant"></a>
Public key for PrivateKey(1) — the generator point G. Used when +counterparty:
'anyone'+ so any party can verify.

## Public Instance Methods
### `initialize(wallet:, originator: = nil)` <a id="method-i-initialize"></a> <a id="initialize-instance_method"></a>
- **@param** `wallet` [#get_public_key, #create_signature] BRC-100 wallet interface
- **@param** `originator` [String, nil] optional FQDN of the originating application
- **@return** [PushDropTemplate] a new instance of PushDropTemplate

### `lock(fields:, protocol_id:, key_id:, counterparty:, include_signature: = true, lock_position: = :before)` <a id="method-i-lock"></a> <a id="lock-instance_method"></a>
Create a PushDrop locking script for the given data fields.

Derives a public key from the wallet using the supplied protocol parameters,
then builds a P2PKH locking condition from it. When +include_signature: true+
(the default), signs the concatenation of all fields and appends the DER
signature as an additional field.

When `counterparty` is +'anyone'+, the generator point (PrivateKey(1) public
key) is used directly as the locking key. This is the convention for tokens
that any party can verify.

The `lock_position` parameter controls where the P2PKH locking condition is
placed relative to the data fields. Defaults to <code>:before</code> (lock
first, then fields and drops), matching the ts-sdk convention.

**Breaking change (v0.9):** the default changed from <code>:after</code> to
<code>:before</code>. Callers that relied on the old layout must pass
+lock_position: :after+.
- **@param** `fields` [Array<String>] data payloads to embed (binary strings)
- **@param** `protocol_id` [Array] two-element [security_level, protocol_name]
- **@param** `key_id` [String] key identifier
- **@param** `counterparty` [String] 'self', 'anyone', or a hex public key
- **@param** `include_signature` [Boolean] whether to append an ECDSA field signature
- **@param** `lock_position` [Symbol] +:before+ (default) or +:after+
- **@raise** [ArgumentError] if fields is empty
- **@return** [BSV::Script::Script] the PushDrop locking script

### `unlock(protocol_id:, key_id:, counterparty:)` <a id="method-i-unlock"></a> <a id="unlock-instance_method"></a>
Return an unlocker for spending a PushDrop token output.

The returned {Unlocker} follows the unlocking template interface and can be
assigned to an input's `unlocking_script_template`.
- **@param** `protocol_id` [Array] two-element [security_level, protocol_name]
- **@param** `key_id` [String] key identifier
- **@param** `counterparty` [String] 'self', 'anyone', or a hex public key
- **@return** [Unlocker] object with +#sign+ and +#estimated_length+
