Steemit-WsClient

 view release on metacpan or  search on metacpan

lib/Steemit/WsClient.pm  view on Meta::CPAN


use Modern::Perl;
use Mojo::Base -base;
use Mojo::UserAgent;
use Mojo::JSON qw(decode_json encode_json);
use Data::Dumper;

has url                => 'https://api.steemit.com/';
has ua                 => sub { Mojo::UserAgent->new };
has posting_key        => undef;
has plain_posting_key  => \&_transform_private_key;


=head2 all database api methods of the steemit api

L<https://github.com/steemit/steem/blob/master/libraries/app/database_api.cpp>

      get_miner_queue
      lookup_account_names
      get_discussions
      get_discussions_by_blog

lib/Steemit/WsClient.pm  view on Meta::CPAN

   my $transaction = {
      ref_block_num => ( $block_number - 1 )& 0xffff,
      ref_block_prefix => unpack( "xxxxV", pack('H*',$ref_block_id)),
      expiration       => $expiration,
      operations       => [@operations],
      extensions => [],
      signatures => [],
   };
   my $serialized_transaction = $self->_serialize_transaction_message( $transaction );

   my $bin_private_key = $self->plain_posting_key;
   require Steemit::ECDSA;
   my ( $r, $s, $i ) = Steemit::ECDSA::ecdsa_sign( $serialized_transaction, Math::BigInt->from_bytes( $bin_private_key ) );
   $i += 4;
   $i += 27;

   my $signature = join('', map { unpack 'H*', $_ } ( pack("C", $i ), map { $_->as_bytes} ($r,$s )) );
   unless( Steemit::ECDSA::is_signature_canonical_canonical( pack "H*", $signature ) ){
      die "signature $signature is not canonical";
   }

   $transaction->{signatures} = [ $signature ];

lib/Steemit/WsClient.pm  view on Meta::CPAN

      my $checksum = $rip->digest;
      $rip->reset;
      $rip->add('');
      $self->{public_posting_key} = "STM".Steemit::Base58::encode_base58($bin_pubkey.substr($checksum,0,4));
   }

   return $self->{public_posting_key}
}


sub _transform_private_key {
   my( $self ) = @_;
   die "posting_key missing" unless( $self->posting_key );

   my $base58 = $self->posting_key;

   require Steemit::Base58;
   my $binary = Steemit::Base58::decode_base58( $base58 );


   my $version            = substr( $binary, 0, 1 );
   my $binary_private_key = substr( $binary, 1, -4);
   my $checksum           = substr( $binary, -4);
   die "invalid version in wif ( 0x80 needed ) " unless $version eq  pack "H*", '80';

   require Digest::SHA;
   my $generated_checksum = substr( Digest::SHA::sha256( Digest::SHA::sha256( $version.$binary_private_key )), 0, 4 );

   die "invalid checksum " unless $generated_checksum eq $checksum;

   return $binary_private_key;
}

sub _serialize_transaction_message  {
   my ($self,$transaction) = @_;

   my $serialized_transaction;

   $serialized_transaction .= pack 'v', $transaction->{ref_block_num};

   $serialized_transaction .= pack 'V', $transaction->{ref_block_prefix};

t/01-keys.t  view on Meta::CPAN


use_ok( 'Steemit::WsClient' ) || print "Bail out!\n";

diag( "Testing Steemit $Steemit::WsClient::VERSION, Perl $], $^X" );

my $wif = '5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ';
my $steem = Steemit::WsClient->new( posting_key => $wif );



my $binary_private_key = $steem->plain_posting_key();
my $hex_key = unpack "H*", $binary_private_key;

is( uc( $hex_key) , '0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D', "private key correctly extracted from wif format" );

isa_ok( $steem, 'Steemit::WsClient', 'constructor will return a Steemit object');

$wif = '5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTG';
$steem = Steemit::WsClient->new( posting_key => $wif );
eval{ $steem->plain_posting_key() };
my $error = $@;
like( $error, qr/invalid checksum/, 'checksum is checked' );

t/01-keys.t  view on Meta::CPAN

$steem = Steemit::WsClient->new( posting_key => $wif );
eval{ $steem->plain_posting_key() };
$error = $@;
like( $error, qr/invalid version/, 'version is checked' );


sub data {
    return {
        wif => '',
        decoded_base58 => '',
        private_key    => '',
    }
}



( run in 0.260 second using v1.01-cache-2.11-cpan-a5abf4f5562 )