class Webull::Authenticator

Authenticator generates access/refresh tokens from a username/password

Attributes

udid[R]

Public Class Methods

new(udid) click to toggle source
# File lib/webull/authenticator.rb, line 29
def initialize(udid)
  @udid = udid
end

Public Instance Methods

generate_tokens() click to toggle source
# File lib/webull/authenticator.rb, line 33
def generate_tokens # rubocop:disable Metrics/MethodLength
  params = {
    account: username,
    accountType: 2,
    deviceId: udid,
    regionId: 6,
    grade: 1,
    pwd: hashed_password,
    verificationCode: mfa
  }
  resp = HTTParty.post(
    'https://userapi.webull.com/api/passport/login/v3/account',
    body: params.to_json,
    headers: { 'Content-Type' => 'application/json' }
  )
  raise("Login request failed: #{resp.code}") unless resp.success?
  Tokens.from_resp(resp)
end

Private Instance Methods

generate_mfa!() click to toggle source
# File lib/webull/authenticator.rb, line 63
def generate_mfa!
  HTTParty.get(
    'https://userapi.webull.com/api/passport/verificationCode/sendCode',
    query: {
      account: username,
      accountType: 2,
      deviceId: udid,
      codeType: 5,
      regionCode: 1
    }
  )
end
hashed_password() click to toggle source
# File lib/webull/authenticator.rb, line 91
def hashed_password
  @hashed_password ||= Digest::MD5.hexdigest("wl_app-a&b@!423^#{password}")
end
mfa() click to toggle source
# File lib/webull/authenticator.rb, line 54
def mfa
  return @mfa if @mfa
  generate_mfa!
  @mfa = UserInput.new(
    message: 'Webull MFA code',
    validation: /^\d{6}$/
  ).ask
end
password() click to toggle source
# File lib/webull/authenticator.rb, line 83
def password
  @password ||= UserInput.new(
    message: 'Webull password',
    secret: true,
    validation: /.*/
  ).ask
end
username() click to toggle source
# File lib/webull/authenticator.rb, line 76
def username
  @username ||= UserInput.new(
    message: 'Webull username',
    validation: /^.*@.*$/
  ).ask
end